AvTranscoder  0.9.4
C++APIforLibav/FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
FormatContext.cpp
Go to the documentation of this file.
1 #include "FormatContext.hpp"
2 
3 #include <stdexcept>
4 #include <sstream>
5 
6 namespace avtranscoder
7 {
8 
9 FormatContext::FormatContext(const std::string& filename, int req_flags, AVDictionary** options)
10  : _avFormatContext(NULL)
11  , _flags(req_flags)
12  , _options()
13  , _isOpen(false)
14 {
15  int ret = avformat_open_input(&_avFormatContext, filename.c_str(), NULL, options);
16  if(ret < 0)
17  {
18  std::string msg = "Unable to open file ";
19  msg += filename;
20  msg += ": ";
21  msg += getDescriptionFromErrorCode(ret);
22  throw std::ios_base::failure(msg);
23  }
24  _isOpen = true;
25 
27  // when demuxing, priv_data of AVFormatContext is set by avformat_open_input()
28  if(_avFormatContext->iformat->priv_class)
29  loadOptions(_options, _avFormatContext->priv_data, req_flags);
30 }
31 
33  : _avFormatContext(NULL)
34  , _flags(req_flags)
35  , _options()
36  , _isOpen(false)
37 {
38  _avFormatContext = avformat_alloc_context();
40 }
41 
43 {
44  if(!_avFormatContext)
45  return;
46 
47  if(_isOpen)
48  avformat_close_input(&_avFormatContext);
49  else
50  avformat_free_context(_avFormatContext);
51  _avFormatContext = NULL;
52 }
53 
54 void FormatContext::findStreamInfo(AVDictionary** options)
55 {
56  const int err = avformat_find_stream_info(_avFormatContext, options);
57  if(err < 0)
58  {
59  throw std::ios_base::failure("Unable to find stream informations: " + getDescriptionFromErrorCode(err));
60  }
61 }
62 
63 void FormatContext::openRessource(const std::string& url, int flags)
64 {
65  if((_avFormatContext->flags & AVFMT_NOFILE) == AVFMT_NOFILE)
66  return;
67 
68  const int err = avio_open2(&_avFormatContext->pb, url.c_str(), flags, NULL, NULL);
69  if(err < 0)
70  {
71  throw std::ios_base::failure("Error when opening output format: " + getDescriptionFromErrorCode(err));
72  }
73 }
74 
76 {
77  if((_avFormatContext->flags & AVFMT_NOFILE) == AVFMT_NOFILE)
78  return;
79 
80  const int err = avio_close(_avFormatContext->pb);
81  if(err < 0)
82  {
83  throw std::ios_base::failure("Error when close output format: " + getDescriptionFromErrorCode(err));
84  }
85 }
86 
87 void FormatContext::writeHeader(AVDictionary** options)
88 {
89  const int ret = avformat_write_header(_avFormatContext, options);
90  if(ret != 0)
91  {
92  throw std::runtime_error("Could not write header: " + getDescriptionFromErrorCode(ret));
93  }
94  // when muxing, priv_data of AVFormatContext is set by avformat_write_header()
95  if(_avFormatContext->oformat->priv_class)
97 }
98 
99 void FormatContext::writeFrame(AVPacket& packet, bool interleaved)
100 {
101  int ret = 0;
102  if(interleaved)
103  ret = av_interleaved_write_frame(_avFormatContext, &packet);
104  else
105  {
106  // returns 1 if flushed and there is no more data to flush
107  ret = av_write_frame(_avFormatContext, &packet);
108  }
109 
110  if(ret < 0)
111  {
112  throw std::runtime_error("Error when writting packet in stream: " + getDescriptionFromErrorCode(ret));
113  }
114 }
115 
117 {
118  const int ret = av_write_trailer(_avFormatContext);
119  if(ret != 0)
120  {
121  throw std::runtime_error("Could not write trailer: " + getDescriptionFromErrorCode(ret));
122  }
123 }
124 
125 void FormatContext::addMetaData(const std::string& key, const std::string& value)
126 {
127  const int ret = av_dict_set(&_avFormatContext->metadata, key.c_str(), value.c_str(), 0);
128  if(ret < 0)
129  {
131  }
132 }
133 
134 AVStream& FormatContext::addAVStream(const AVCodec& avCodec)
135 {
136  // Need const_cast<AVCodec*> for libav versions < 54.34.
137  AVStream* stream = avformat_new_stream(_avFormatContext, const_cast<AVCodec*>(&avCodec));
138  if(stream == NULL)
139  {
140  throw std::runtime_error("Unable to add new video stream");
141  }
142  return *stream;
143 }
144 
145 bool FormatContext::seek(const uint64_t position, const int flag)
146 {
147  LOG_INFO("Seek in '" << _avFormatContext->filename << "' at " << position << " with flag '"<< flag << "'")
148  const int err = av_seek_frame(_avFormatContext, -1, position, flag);
149  if(err < 0)
150  {
151  LOG_ERROR("Error when seek at " << position << " (in AV_TIME_BASE units) in file")
153  return false;
154  }
155  return true;
156 }
157 
158 std::vector<Option> FormatContext::getOptions()
159 {
160  std::vector<Option> optionsArray;
161  for(OptionMap::iterator it = _options.begin(); it != _options.end(); ++it)
162  {
163  optionsArray.push_back(it->second);
164  }
165  return optionsArray;
166 }
167 
168 AVStream& FormatContext::getAVStream(size_t index) const
169 {
170  if(index >= getNbStreams())
171  {
172  std::stringstream msg;
173  msg << "Can't acces stream at index ";
174  msg << index;
175  throw std::runtime_error(msg.str());
176  }
177  return *_avFormatContext->streams[index];
178 }
179 
180 void FormatContext::setFilename(const std::string& filename)
181 {
182  strcpy(&_avFormatContext->filename[0], filename.c_str());
183 }
184 
185 void FormatContext::setOutputFormat(const std::string& filename, const std::string& shortName, const std::string& mimeType)
186 {
187  AVOutputFormat* oformat = av_guess_format(shortName.c_str(), filename.c_str(), mimeType.c_str());
188  if(!oformat)
189  {
190  std::string msg("Unable to find format for ");
191  msg += filename;
192  if(!shortName.empty())
193  {
194  msg += ", formatName = ";
195  msg += shortName;
196  }
197  if(!mimeType.empty())
198  {
199  msg += ", mimeType = ";
200  msg += mimeType;
201  }
202  throw std::ios_base::failure(msg);
203  }
204 
205  _avFormatContext->oformat = oformat;
206 }
207 }
#define LOG_ERROR(...)
Definition: log.hpp:35
const int _flags
Flags with which the options are loaded (see AV_OPT_FLAG_xxx)
void closeRessource()
Close the resource accessed by the AVIOContext and free it.
void loadOptions(OptionMap &outOptions, void *av_class, int req_flags)
Definition: Option.cpp:227
bool seek(const uint64_t position, const int flag)
Seek at a specific position.
void setOutputFormat(const std::string &filename, const std::string &shortName="", const std::string &mimeType="")
std::string getDescriptionFromErrorCode(const int code)
Get the string description corresponding to the error code provided by ffmpeg/libav.
Definition: common.cpp:22
void addMetaData(const std::string &key, const std::string &value)
AVStream & addAVStream(const AVCodec &avCodec)
#define LOG_INFO(...)
Definition: log.hpp:23
void writeTrailer()
Write the stream trailer to an output media file.
OptionArray getOptions()
Get options as array.
void writeHeader(AVDictionary **options=NULL)
Write the stream header to an output media file.
bool _isOpen
Is the AVFormatContext open (in constructor with a filename)
void findStreamInfo(AVDictionary **options=NULL)
Read packets of a media file to get stream information.
void writeFrame(AVPacket &packet, bool interleaved=true)
Write a packet to an output media file.
AVFormatContext * _avFormatContext
Has ownership.
void openRessource(const std::string &url, int flags)
Create and initialize a AVIOContext for accessing the resource indicated by url.
FormatContext(const FormatContext &formatContext)
AVStream & getAVStream(size_t index) const
void setFilename(const std::string &filename)