AvTranscoder  0.9.4
C++APIforLibav/FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
ICodec.cpp
Go to the documentation of this file.
1 #include "ICodec.hpp"
2 
3 extern "C" {
4 #include <libavutil/mem.h>
5 }
6 
7 #include <stdexcept>
8 #include <cassert>
9 
10 namespace avtranscoder
11 {
12 
13 ICodec::ICodec(const ECodecType type, const std::string& codecName)
14  : _avCodecContext(NULL)
15  , _avCodec(NULL)
16  , _isCodecContextAllocated(true)
17  , _type(type)
18 {
19  setCodec(type, codecName);
22 }
23 
24 ICodec::ICodec(const ECodecType type, const AVCodecID codecId)
25  : _avCodecContext(NULL)
26  , _avCodec(NULL)
27  , _isCodecContextAllocated(true)
28  , _type(type)
29 {
30  setCodec(type, codecId);
33 }
34 
35 ICodec::ICodec(const ECodecType type, AVCodecContext& avCodecContext)
36  : _avCodecContext(&avCodecContext)
37  , _avCodec(NULL)
38  , _isCodecContextAllocated(false)
39  , _type(type)
40 {
41  setCodec(type, _avCodecContext->codec_id);
43 }
44 
46 {
47  avcodec_close(_avCodecContext);
48 
50  return;
51 
52  av_free(_avCodecContext);
53  _avCodecContext = NULL;
54 }
55 
57 {
58  if(!_avCodecContext)
59  throw std::runtime_error("Unable to open a codec without codec context");
60 
61  const int ret = avcodec_open2(_avCodecContext, _avCodec, NULL);
62  if(ret < 0)
63  {
64  std::string msg = "Unable to open codec: ";
65 
66  if(_avCodec && _avCodec->long_name)
67  msg += _avCodec->long_name;
68 
69  if(_avCodec && _avCodec->name)
70  {
71  msg += " (";
72  msg += _avCodec->name;
73  msg += ") ";
74  }
75 
76  avcodec_close(_avCodecContext);
77 
78  msg += getDescriptionFromErrorCode(ret);
79 
80  throw std::runtime_error(msg);
81  }
82 }
83 
84 std::string ICodec::getCodecName() const
85 {
86  assert(_avCodecContext != NULL);
87  const AVCodecDescriptor* desc = avcodec_descriptor_get(_avCodecContext->codec_id);
88  if(!desc)
89  throw std::runtime_error("Codec Descriptor is not available.");
90 
91  return desc->name;
92 }
93 
95 {
96  assert(_avCodecContext != NULL);
97  return _avCodecContext->codec_id;
98 }
99 
101 {
102  assert(_avCodecContext != NULL);
103  return _avCodecContext->delay;
104 }
105 
106 std::vector<Option> ICodec::getOptions()
107 {
108  std::vector<Option> optionsArray;
109  for(OptionMap::iterator it = _options.begin(); it != _options.end(); ++it)
110  {
111  optionsArray.push_back(it->second);
112  }
113  return optionsArray;
114 }
115 
116 void ICodec::setCodec(const ECodecType type, const std::string& codecName)
117 {
118  const AVCodecDescriptor* avCodecDescriptor = avcodec_descriptor_get_by_name(codecName.c_str());
119  if(!avCodecDescriptor)
120  {
121  std::string msg("Unable to find codec ");
122  msg += codecName;
123  throw std::runtime_error(msg);
124  }
125 
126  setCodec(type, avCodecDescriptor->id);
127 }
128 
129 void ICodec::setCodec(const ECodecType type, const AVCodecID codecId)
130 {
131  if(codecId == 0)
132  {
133  LOG_WARN("Unsupported codec with id 0")
134  return;
135  }
136 
137  if(type == eCodecTypeEncoder)
138  _avCodec = avcodec_find_encoder(codecId);
139  else if(type == eCodecTypeDecoder)
140  _avCodec = avcodec_find_decoder(codecId);
141 
142  if(_avCodecContext)
143  _avCodecContext->codec = _avCodec;
144 }
145 
147 {
148  _avCodecContext = avcodec_alloc_context3(_avCodec);
149  if(!_avCodecContext)
150  {
151  throw std::runtime_error("Unable to allocate the codecContext and set its fields to default values");
152  }
153  _avCodecContext->codec = _avCodec;
154 }
155 
157 {
158  if(_type == eCodecTypeEncoder)
159  {
160  loadOptions(_options, _avCodecContext, AV_OPT_FLAG_ENCODING_PARAM);
161  // load specific options of the codec
162  loadOptions(_options, _avCodecContext->priv_data, AV_OPT_FLAG_ENCODING_PARAM);
163  }
164  else if(_type == eCodecTypeDecoder)
165  {
166  loadOptions(_options, _avCodecContext, AV_OPT_FLAG_DECODING_PARAM);
167  // load specific options of the codec
168  loadOptions(_options, _avCodecContext->priv_data, AV_OPT_FLAG_DECODING_PARAM);
169  }
170 }
171 }
#define AVCodecID
Definition: common.hpp:45
OptionMap _options
Definition: ICodec.hpp:72
void loadOptions(OptionMap &outOptions, void *av_class, int req_flags)
Definition: Option.cpp:227
ICodec(const ICodec &iCodec)
std::string getDescriptionFromErrorCode(const int code)
Get the string description corresponding to the error code provided by ffmpeg/libav.
Definition: common.cpp:22
AVCodecContext * _avCodecContext
Full codec instance description (has ownership)
Definition: ICodec.hpp:66
AVCodec * _avCodec
Codec abstract description.
Definition: ICodec.hpp:67
ECodecType
Define if a codec is for encoding or decoding.
Definition: ICodec.hpp:19
ECodecType _type
Definition: ICodec.hpp:70
void loadCodecOptions()
Definition: ICodec.cpp:156
#define LOG_WARN(...)
Definition: log.hpp:29
int getLatency() const
Definition: ICodec.cpp:100
AVCodecID getCodecId() const
Definition: ICodec.cpp:94
std::string getCodecName() const
Definition: ICodec.cpp:84
const bool _isCodecContextAllocated
Is the AVCodecContext allocated by the class.
Definition: ICodec.hpp:68
OptionArray getOptions()
Get options as array.
Definition: ICodec.cpp:106
virtual ~ICodec()=0
Definition: ICodec.cpp:45
void openCodec()
Initialize the codec context.
Definition: ICodec.cpp:56
void setCodec(const ECodecType type, const std::string &codecName)
Definition: ICodec.cpp:116
void allocateContext()
Definition: ICodec.cpp:146