AvTranscoder  0.9.4
C++APIforLibav/FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
InputFile.cpp
Go to the documentation of this file.
1 #include "InputFile.hpp"
2 
10 
11 extern "C" {
12 #include <libavcodec/avcodec.h>
13 #include <libavutil/avutil.h>
14 #include <libavutil/pixdesc.h>
15 }
16 
17 #include <stdexcept>
18 #include <sstream>
19 
20 namespace avtranscoder
21 {
22 
23 InputFile::InputFile(const std::string& filename)
24  : _formatContext(filename, AV_OPT_FLAG_DECODING_PARAM)
25  , _properties(NULL)
26  , _filename(filename)
27  , _inputStreams()
28 {
29  // Fill the FormatContext with the stream information
31 
32  // Get the stream information as properties
34 
35  // Create streams
36  for(size_t streamIndex = 0; streamIndex < _formatContext.getNbStreams(); ++streamIndex)
37  {
38  _inputStreams.push_back(new InputStream(*this, streamIndex));
39  }
40 }
41 
43 {
44  delete _properties;
45  for(std::vector<InputStream*>::iterator it = _inputStreams.begin(); it != _inputStreams.end(); ++it)
46  {
47  delete(*it);
48  }
49 }
50 
51 void InputFile::analyse(IProgress& progress, const EAnalyseLevel level)
52 {
53  _properties->extractStreamProperties(progress, level);
54 }
55 
56 FileProperties InputFile::analyseFile(const std::string& filename, IProgress& progress, const EAnalyseLevel level)
57 {
58  InputFile file(filename);
59  file.analyse(progress, level);
60  return file.getProperties();
61 }
62 
63 bool InputFile::readNextPacket(CodedData& data, const size_t streamIndex)
64 {
65  bool nextPacketFound = false;
66  while(!nextPacketFound)
67  {
68  const int ret = av_read_frame(&_formatContext.getAVFormatContext(), &data.getAVPacket());
69  if(ret < 0) // error or end of file
70  {
71  LOG_INFO("Stop reading the next frame of file '" << _filename << "', stream " << streamIndex << " (" << getDescriptionFromErrorCode(ret) << ")")
72  return false;
73  }
74 
75  // Add Stream info to the packet
76  data.refAVStream(_formatContext.getAVStream(streamIndex));
77 
78  // if the packet stream is the expected one
79  // return the packet data
80  const int packetStreamIndex = data.getAVPacket().stream_index;
81  if(packetStreamIndex == (int)streamIndex)
82  {
83  LOG_DEBUG("Get a packet from stream " << streamIndex)
84  nextPacketFound = true;
85  }
86  // else add the packet data to the stream cache
87  else
88  {
89  _inputStreams.at(packetStreamIndex)->addPacket(data.getAVPacket());
90  data.clear();
91  }
92  }
93  return true;
94 }
95 
96 bool InputFile::seekAtFrame(const size_t frame, const int flag)
97 {
98  const uint64_t position = frame / getFps() * AV_TIME_BASE;
99  return _formatContext.seek(position, flag);
100 }
101 
102 bool InputFile::seekAtTime(const double time, const int flag)
103 {
104  const uint64_t position = time * AV_TIME_BASE;
105  return _formatContext.seek(position, flag);
106 }
107 
108 void InputFile::activateStream(const size_t streamIndex, bool activate)
109 {
110  getStream(streamIndex).activate(activate);
111 }
112 
114 {
115  try
116  {
117  return *_inputStreams.at(index);
118  }
119  catch(const std::out_of_range& e)
120  {
121  std::stringstream msg;
122  msg << getFilename();
123  msg << " has no stream at index ";
124  msg << index;
125  throw std::runtime_error(msg.str());
126  }
127 }
128 
130 {
131  double fps = 1;
133  fps = _properties->getVideoProperties().at(0).getFps();
134  return fps;
135 }
136 
138 {
139  // check the given profile
140  const bool isValid = ProfileLoader::checkFormatProfile(profile);
141  if(!isValid)
142  {
143  std::string msg("Invalid format profile to setup unwrapping.");
144  LOG_ERROR(msg)
145  throw std::runtime_error(msg);
146  }
147 
148  if(!profile.empty())
149  {
150  LOG_INFO("Setup unwrapping with:\n" << profile)
151  }
152 
153  for(ProfileLoader::Profile::const_iterator it = profile.begin(); it != profile.end(); ++it)
154  {
156  (*it).first == constants::avProfileType)
157  continue;
158 
159  try
160  {
161  Option& formatOption = _formatContext.getOption((*it).first);
162  formatOption.setString((*it).second);
163  }
164  catch(std::exception& e)
165  {
166  LOG_WARN("InputFile - can't set option " << (*it).first << " to " << (*it).second << ": " << e.what())
167  }
168  }
169 }
170 
171 std::ostream& operator<<(std::ostream& flux, const InputFile& input)
172 {
173  // wrapper
174  flux << input.getProperties();
175 
176  // video streams
177  for(size_t videoStreamIndex = 0; videoStreamIndex < input.getProperties().getNbVideoStreams(); ++videoStreamIndex)
178  {
179  flux << input.getProperties().getVideoProperties().at(videoStreamIndex);
180  }
181 
182  // audio streams
183  for(size_t audioStreamIndex = 0; audioStreamIndex < input.getProperties().getNbAudioStreams(); ++audioStreamIndex)
184  {
185  flux << input.getProperties().getAudioProperties().at(audioStreamIndex);
186  }
187 
188  // data streams
189  for(size_t dataStreamIndex = 0; dataStreamIndex < input.getProperties().getNbDataStreams(); ++dataStreamIndex)
190  {
191  flux << input.getProperties().getDataProperties().at(dataStreamIndex);
192  }
193 
194  // subtitle streams
195  for(size_t subtitleStreamIndex = 0; subtitleStreamIndex < input.getProperties().getNbSubtitleStreams();
196  ++subtitleStreamIndex)
197  {
198  flux << input.getProperties().getSubtitleProperties().at(subtitleStreamIndex);
199  }
200 
201  // attachement streams
202  for(size_t attachementStreamIndex = 0; attachementStreamIndex < input.getProperties().getNbAttachementStreams();
203  ++attachementStreamIndex)
204  {
205  flux << input.getProperties().getAttachementProperties().at(attachementStreamIndex);
206  }
207 
208  // unknown streams
209  for(size_t unknownStreamIndex = 0; unknownStreamIndex < input.getProperties().getNbUnknownStreams();
210  ++unknownStreamIndex)
211  {
212  flux << input.getProperties().getUnknownProperties().at(unknownStreamIndex);
213  }
214 
215  return flux;
216 }
217 }
const std::vector< avtranscoder::AudioProperties > & getAudioProperties() const
const std::vector< avtranscoder::UnknownProperties > & getUnknownProperties() const
Base class of Progress. Inherit this class to have your own way to manage a progress bar...
Definition: IProgress.hpp:23
const std::vector< avtranscoder::VideoProperties > & getVideoProperties() const
void setString(const std::string &value)
Definition: Option.cpp:187
EAnalyseLevel
Level of file analysis.
Definition: util.hpp:10
#define LOG_ERROR(...)
Definition: log.hpp:35
const std::vector< avtranscoder::SubtitleProperties > & getSubtitleProperties() const
void extractStreamProperties(IProgress &progress, const EAnalyseLevel level)
Relaunch streams analysis with a specific level.
static bool checkFormatProfile(const Profile &profileToCheck)
void analyse(IProgress &progress, const EAnalyseLevel level=eAnalyseLevelFirstGop)
Run the analyse on the file after a setup. call this function before getProperties().
Definition: InputFile.cpp:51
bool seekAtTime(const double time, const int flag=AVSEEK_FLAG_ANY)
Definition: InputFile.cpp:102
void clear()
Clear existing data and set size to 0.
Definition: CodedData.cpp:71
bool seek(const uint64_t position, const int flag)
Seek at a specific position.
const std::vector< avtranscoder::AttachementProperties > & getAttachementProperties() const
std::vector< InputStream * > _inputStreams
Has ownership.
Definition: InputFile.hpp:111
std::string getDescriptionFromErrorCode(const int code)
Get the string description corresponding to the error code provided by ffmpeg/libav.
Definition: common.cpp:22
std::string getFilename() const
Definition: InputFile.hpp:80
size_t getNbSubtitleStreams() const
AVPacket & getAVPacket()
Definition: CodedData.hpp:78
std::map< std::string, std::string > Profile
const std::string avProfileIdentificator
const std::string avProfileIdentificatorHuman
#define LOG_INFO(...)
Definition: log.hpp:23
InputFile(const InputFile &inputFile)
void refAVStream(const AVStream &avStream)
Definition: CodedData.hpp:42
bool seekAtFrame(const size_t frame, const int flag=AVSEEK_FLAG_ANY)
Seek at a specific frame / time (in seconds)
Definition: InputFile.cpp:96
void activate(const bool activate=true)
Functions about buffering Activate the stream will buffered its data when read packets.
Definition: InputStream.hpp:34
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
Option & getOption(const std::string &optionName)
void activateStream(const size_t streamIndex, const bool activate=true)
Activate the indicated stream.
Definition: InputFile.cpp:108
const FileProperties & getProperties() const
Return media properties on the current InputFile.
Definition: InputFile.hpp:71
const std::vector< avtranscoder::DataProperties > & getDataProperties() const
virtual void setupUnwrapping(const ProfileLoader::Profile &profile)
Set the format of the input file.
Definition: InputFile.cpp:137
#define LOG_WARN(...)
Definition: log.hpp:29
double getFps()
Get Fps from first video stream.
Definition: InputFile.cpp:129
void findStreamInfo(AVDictionary **options=NULL)
Read packets of a media file to get stream information.
FormatContext _formatContext
Definition: InputFile.hpp:108
FileProperties * _properties
Definition: InputFile.hpp:109
static FileProperties analyseFile(const std::string &filename, IProgress &progress, const EAnalyseLevel level=eAnalyseLevelFirstGop)
Get media file properties using static method.
Definition: InputFile.cpp:56
size_t getNbAttachementStreams() const
#define LOG_DEBUG(...)
Definition: log.hpp:17
This class describes coded data.
Definition: CodedData.hpp:18
size_t getNbUnknownStreams() const
AVFormatContext & getAVFormatContext() const
InputStream & getStream(size_t index)
Get stream type: video, audio, subtitle, etc.
Definition: InputFile.cpp:113
const std::string avProfileType
bool readNextPacket(CodedData &data, const size_t streamIndex)
Read the next packet of the specified stream.
Definition: InputFile.cpp:63
AVStream & getAVStream(size_t index) const