AvTranscoder  0.9.4
C++APIforLibav/FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
VideoEncoder.cpp
Go to the documentation of this file.
1 #include "VideoEncoder.hpp"
2 
3 extern "C" {
4 #include <libavcodec/avcodec.h>
5 #include <libavformat/avformat.h>
6 #include <libavutil/avutil.h>
7 }
8 
9 #include <stdexcept>
10 #include <cstdlib>
11 
12 namespace avtranscoder
13 {
14 
15 VideoEncoder::VideoEncoder(const std::string& videoCodecName)
16  : _codec(eCodecTypeEncoder, videoCodecName)
17 {
18 }
19 
21 {
22 }
23 
25 {
26  if(!profile.empty())
27  {
28  LOG_INFO("Setup video encoder with:\n" << profile)
29  }
30 
31  // set width, height, pixel format, fps
32  _codec.setImageParameters(frameDesc);
33 
34  // setup encoder
35  setupEncoder(profile);
36 }
37 
39 {
40  // check the given profile
41  const bool isValid = ProfileLoader::checkVideoProfile(profile);
42  if(!isValid && !profile.empty())
43  {
44  const std::string msg("Invalid video profile to setup encoder.");
45  LOG_ERROR(msg)
46  throw std::runtime_error(msg);
47  }
48 
49  // set threads before any other options
50  if(profile.count(constants::avProfileThreads))
52  else
54 
55  // set encoder options
56  for(ProfileLoader::Profile::const_iterator it = profile.begin(); it != profile.end(); ++it)
57  {
59  (*it).first == constants::avProfileType || (*it).first == constants::avProfileCodec ||
60  (*it).first == constants::avProfileWidth || (*it).first == constants::avProfileHeight ||
61  (*it).first == constants::avProfilePixelFormat || (*it).first == constants::avProfileFrameRate ||
62  (*it).first == constants::avProfileThreads)
63  continue;
64 
65  try
66  {
67  Option& encodeOption = _codec.getOption((*it).first);
68  encodeOption.setString((*it).second);
69  }
70  catch(std::exception& e)
71  {
72  }
73  }
74 
75  // open encoder
76  int encoderFlags = 0;
77  if(profile.count(constants::avProfileProcessStat))
78  {
79  LOG_INFO("SetUp video encoder to compute statistics during process")
80  encoderFlags |= CODEC_FLAG_PSNR;
81  }
82  _codec.getAVCodecContext().flags |= encoderFlags;
83  _codec.openCodec();
84 
85  // after open encoder, set specific encoder options
86  for(ProfileLoader::Profile::const_iterator it = profile.begin(); it != profile.end(); ++it)
87  {
89  (*it).first == constants::avProfileType || (*it).first == constants::avProfileCodec ||
90  (*it).first == constants::avProfileWidth || (*it).first == constants::avProfileHeight ||
91  (*it).first == constants::avProfilePixelFormat || (*it).first == constants::avProfileFrameRate ||
92  (*it).first == constants::avProfileThreads)
93  continue;
94 
95  try
96  {
97  Option& encodeOption = _codec.getOption((*it).first);
98  encodeOption.setString((*it).second);
99  }
100  catch(std::exception& e)
101  {
102  LOG_WARN("VideoEncoder - can't set option " << (*it).first << " to " << (*it).second << ": " << e.what())
103  }
104  }
105 }
106 
107 bool VideoEncoder::encodeFrame(const Frame& sourceFrame, CodedData& codedFrame)
108 {
109  AVCodecContext& avCodecContext = _codec.getAVCodecContext();
110 
111  AVPacket& packet = codedFrame.getAVPacket();
112  if((avCodecContext.coded_frame) && (avCodecContext.coded_frame->pts != (int)AV_NOPTS_VALUE))
113  {
114  packet.pts = avCodecContext.coded_frame->pts;
115  }
116 
117  if(avCodecContext.coded_frame && avCodecContext.coded_frame->key_frame)
118  {
119  packet.flags |= AV_PKT_FLAG_KEY;
120  }
121 
122  return encode(&sourceFrame.getAVFrame(), packet);
123 }
124 
126 {
127  return encode(NULL, codedFrame.getAVPacket());
128 }
129 
130 bool VideoEncoder::encode(const AVFrame* decodedData, AVPacket& encodedData)
131 {
132  // Be sure that data of AVPacket is NULL so that the encoder will allocate it
133  encodedData.data = NULL;
134 
135  AVCodecContext& avCodecContext = _codec.getAVCodecContext();
136 #if LIBAVCODEC_VERSION_MAJOR > 53
137  int gotPacket = 0;
138  const int ret = avcodec_encode_video2(&avCodecContext, &encodedData, decodedData, &gotPacket);
139  if(ret != 0)
140  {
141  throw std::runtime_error("Encode video frame error: avcodec encode video frame - " +
143  }
144  return gotPacket == 1;
145 #else
146  const int ret = avcodec_encode_video(&avCodecContext, encodedData.data, encodedData.size, decodedData);
147  if(ret < 0)
148  {
149  throw std::runtime_error("Encode video frame error: avcodec encode video frame - " +
151  }
152  return true;
153 #endif
154 }
155 
156 }
Description to create a video frame.
Definition: VideoFrame.hpp:21
void setString(const std::string &value)
Definition: Option.cpp:187
#define LOG_ERROR(...)
Definition: log.hpp:35
const std::string avProfileFrameRate
bool encodeFrame(const Frame &sourceFrame, CodedData &codedFrame)
Encode a new frame, and get coded frame.
void setupEncoder(const ProfileLoader::Profile &profile=ProfileLoader::Profile())
Setup the encoder.
const std::string avProfileProcessStat
Do statistics during the process.
void setImageParameters(const VideoFrameDesc &videoFrameDesc)
Definition: VideoCodec.cpp:34
void setInt(const int value)
Definition: Option.cpp:169
void setupVideoEncoder(const VideoFrameDesc &frameDesc, const ProfileLoader::Profile &profile=ProfileLoader::Profile())
std::string getDescriptionFromErrorCode(const int code)
Get the string description corresponding to the error code provided by ffmpeg/libav.
Definition: common.cpp:22
AVPacket & getAVPacket()
Definition: CodedData.hpp:78
std::map< std::string, std::string > Profile
const std::string avProfileIdentificator
const std::string avProfileIdentificatorHuman
const std::string avProfilePixelFormat
#define LOG_INFO(...)
Definition: log.hpp:23
Option & getOption(const std::string &optionName)
Definition: ICodec.hpp:50
Wrapper of AVOption. Get its type to know what the option is about: Int, Double, Ratio, Choice... Parse its array of options to get the potential childs (Choice and Group).
Definition: Option.hpp:36
#define LOG_WARN(...)
Definition: log.hpp:29
VideoEncoder(const std::string &videoCodecName)
This class describes decoded (raw) audio or video data.
Definition: Frame.hpp:16
void openCodec()
Initialize the codec context.
Definition: ICodec.cpp:56
const std::string avProfileWidth
const std::string avProfileHeight
AVCodecContext & getAVCodecContext()
Definition: ICodec.hpp:53
This class describes coded data.
Definition: CodedData.hpp:18
const std::string avProfileCodec
const std::string avProfileThreads
AVFrame & getAVFrame()
Definition: Frame.hpp:88
const std::string avProfileType
bool encode(const AVFrame *decodedData, AVPacket &encodedData)
static bool checkVideoProfile(const Profile &profileToCheck)