AvTranscoder  0.9.4
C++APIforLibav/FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
FileProperties.cpp
Go to the documentation of this file.
1 #include "FileProperties.hpp"
2 
6 
7 #include <stdexcept>
8 #include <sstream>
9 
10 namespace avtranscoder
11 {
12 
14  : _formatContext(&formatContext)
15  , _avFormatContext(&formatContext.getAVFormatContext())
16  , _videoStreams()
17  , _audioStreams()
18  , _dataStreams()
19  , _subtitleStreams()
20  , _attachementStreams()
21  , _unknownStreams()
22 {
25 
26  NoDisplayProgress progress;
28 }
29 
31 {
32  // if the analysis level wiil decode some streams parts, seek at the beginning
33  if(level > eAnalyseLevelHeader && ! isRawFormat())
34  const_cast<FormatContext*>(_formatContext)->seek(0, AVSEEK_FLAG_BACKWARD);
35 
36  // clear properties
38 
39  // reload properties
40  for(size_t streamIndex = 0; streamIndex < _formatContext->getNbStreams(); ++streamIndex)
41  {
42  switch(_formatContext->getAVStream(streamIndex).codec->codec_type)
43  {
44  case AVMEDIA_TYPE_VIDEO:
45  {
46  VideoProperties properties(*_formatContext, streamIndex, progress, level);
47  _videoStreams.push_back(properties);
48  break;
49  }
50  case AVMEDIA_TYPE_AUDIO:
51  {
52  AudioProperties properties(*_formatContext, streamIndex);
53  _audioStreams.push_back(properties);
54  break;
55  }
56  case AVMEDIA_TYPE_DATA:
57  {
58  DataProperties properties(*_formatContext, streamIndex);
59  _dataStreams.push_back(properties);
60  break;
61  }
62  case AVMEDIA_TYPE_SUBTITLE:
63  {
64  SubtitleProperties properties(*_formatContext, streamIndex);
65  _subtitleStreams.push_back(properties);
66  break;
67  }
68  case AVMEDIA_TYPE_ATTACHMENT:
69  {
70  AttachementProperties properties(*_formatContext, streamIndex);
71  _attachementStreams.push_back(properties);
72  break;
73  }
74  case AVMEDIA_TYPE_UNKNOWN:
75  {
76  UnknownProperties properties(*_formatContext, streamIndex);
77  _unknownStreams.push_back(properties);
78  break;
79  }
80  case AVMEDIA_TYPE_NB:
81  {
82  break;
83  }
84  }
85  }
86 
87  // once the streams vectors are filled, add their references the base streams vector
88  for(size_t streamIndex = 0; streamIndex < _videoStreams.size(); ++streamIndex)
89  {
90  const size_t videoStreamIndex = _videoStreams.at(streamIndex).getStreamIndex();
91  _streams[videoStreamIndex] = &_videoStreams.at(streamIndex);
92  }
93 
94  for(size_t streamIndex = 0; streamIndex < _audioStreams.size(); ++streamIndex)
95  {
96  const size_t audioStreamIndex = _audioStreams.at(streamIndex).getStreamIndex();
97  _streams[audioStreamIndex] = &_audioStreams.at(streamIndex);
98  }
99 
100  for(size_t streamIndex = 0; streamIndex < _dataStreams.size(); ++streamIndex)
101  {
102  const size_t dataStreamIndex = _dataStreams.at(streamIndex).getStreamIndex();
103  _streams[dataStreamIndex] = &_dataStreams.at(streamIndex);
104  }
105 
106  for(size_t streamIndex = 0; streamIndex < _subtitleStreams.size(); ++streamIndex)
107  {
108  const size_t subtitleStreamIndex = _subtitleStreams.at(streamIndex).getStreamIndex();
109  _streams[subtitleStreamIndex] = &_subtitleStreams.at(streamIndex);
110  }
111 
112  for(size_t streamIndex = 0; streamIndex < _attachementStreams.size(); ++streamIndex)
113  {
114  const size_t attachementStreamIndex = _attachementStreams.at(streamIndex).getStreamIndex();
115  _streams[attachementStreamIndex] = &_attachementStreams.at(streamIndex);
116  }
117 
118  for(size_t streamIndex = 0; streamIndex < _unknownStreams.size(); ++streamIndex)
119  {
120  const size_t unknownStreamIndex = _unknownStreams.at(streamIndex).getStreamIndex();
121  _streams[unknownStreamIndex] = &_unknownStreams.at(streamIndex);
122  }
123 
124  // if the analysis level has decoded some streams parts, return at the beginning
125  if(level > eAnalyseLevelHeader && ! isRawFormat())
126  const_cast<FormatContext*>(_formatContext)->seek(0, AVSEEK_FLAG_BACKWARD);
127 }
128 
129 std::string FileProperties::getFilename() const
130 {
131  if(!_avFormatContext || !_avFormatContext->filename)
132  throw std::runtime_error("unknown file name");
133  return _avFormatContext->filename;
134 }
135 
136 std::string FileProperties::getFormatName() const
137 {
138  if(!_avFormatContext || !_avFormatContext->iformat || !_avFormatContext->iformat->name)
139  throw std::runtime_error("unknown format name");
140  return _avFormatContext->iformat->name;
141 }
142 
144 {
145  if(!_avFormatContext || !_avFormatContext->iformat || !_avFormatContext->iformat->long_name)
146  throw std::runtime_error("unknown format long name");
147  return _avFormatContext->iformat->long_name;
148 }
149 
151 {
152  if(getNbStreams() != 1)
153  return false;
154  // the format name should be the same as the codec name
155  if(getFormatName() == getStreamProperties().at(0)->getCodecName())
156  return true;
157  return false;
158 }
159 
161 {
162 #if LIBAVFORMAT_VERSION_MAJOR <= 55
163  throw std::runtime_error("cannot get mime type format: libavformat library has a major version <= 55.");
164 #else
165  if(_avFormatContext->iformat->mime_type == NULL)
166  throw std::runtime_error("Unknown demuxer format mime type");
167  return std::string(_avFormatContext->iformat->mime_type);
168 #endif
169 }
170 
172 {
173  if(!_avFormatContext)
174  throw std::runtime_error("unknown format context");
175  return _avFormatContext->nb_programs;
176 }
177 
179 {
180  if(!_avFormatContext)
181  throw std::runtime_error("unknown format context");
182  return 1.0 * (unsigned int)_avFormatContext->start_time / AV_TIME_BASE;
183 }
184 
186 {
187  if(!_avFormatContext)
188  throw std::runtime_error("unknown format context");
189  return 1.0 * _avFormatContext->duration / AV_TIME_BASE;
190 }
191 
193 {
194  if(!_avFormatContext)
195  throw std::runtime_error("unknown format context");
196  return _avFormatContext->bit_rate;
197 }
198 
200 {
201  if(!_avFormatContext)
202  throw std::runtime_error("unknown format context");
203  return _avFormatContext->packet_size;
204 }
205 
207 {
208  avtranscoder::StreamProperties* properties = _streams.find(streamIndex)->second;
209  if(properties)
210  return *properties;
211  std::stringstream os;
212  os << "No stream properties correspond to stream at index ";
213  os << streamIndex;
214  throw std::runtime_error(os.str());
215 }
216 
217 const std::vector<avtranscoder::StreamProperties*> FileProperties::getStreamProperties() const
218 {
219  std::vector<avtranscoder::StreamProperties*> streams;
220  for(std::map<size_t, StreamProperties*>::const_iterator it = _streams.begin(); it != _streams.end(); ++it)
221  {
222  streams.push_back(it->second);
223  }
224  return streams;
225 }
226 
228 {
229  if(!_avFormatContext)
230  throw std::runtime_error("unknown format context");
231  return _avFormatContext->nb_streams;
232 }
233 
235 {
236  PropertyVector propertyVector;
237  return fillVector(propertyVector);
238 }
239 
241 {
242  addProperty(data, "filename", &FileProperties::getFilename);
243  addProperty(data, "formatName", &FileProperties::getFormatName);
244  addProperty(data, "formatLongName", &FileProperties::getFormatLongName);
246 
247  addProperty(data, "startTime", &FileProperties::getStartTime);
248  addProperty(data, "duration", &FileProperties::getDuration);
249  addProperty(data, "bitrate", &FileProperties::getBitRate);
250  addProperty(data, "numberOfStreams", &FileProperties::getNbStreams);
251  addProperty(data, "numberOfPrograms", &FileProperties::getProgramsCount);
252 
253  detail::add(data, "numberOfVideoStreams", getNbVideoStreams());
254  detail::add(data, "numberOfAudioStreams", getNbAudioStreams());
255  detail::add(data, "numberOfDataStreams", getNbDataStreams());
256  detail::add(data, "numberOfSubtitleStreams", getNbSubtitleStreams());
257  detail::add(data, "numberOfAttachementStreams", getNbAttachementStreams());
258  detail::add(data, "numberOfUnknownStreams", getNbUnknownStreams());
259 
260  for(size_t metadataIndex = 0; metadataIndex < _metadatas.size(); ++metadataIndex)
261  {
262  detail::add(data, _metadatas.at(metadataIndex).first, _metadatas.at(metadataIndex).second);
263  }
264 
265  return data;
266 }
267 
269 {
270  PropertyMap dataMap;
271 
272  PropertyVector dataVector(asVector());
273  for(PropertyVector::const_iterator it = dataVector.begin(); it != dataVector.end(); ++it)
274  {
275  dataMap.insert(std::make_pair(it->first, it->second));
276  }
277 
278  return dataMap;
279 }
280 
281 std::string FileProperties::asJson() const
282 {
284  PropertyMap properties = asMap();
285  for(PropertyMap::iterator it = properties.begin(); it != properties.end(); ++it)
286  writer << std::make_pair(it->first.c_str(), it->second.c_str());
287  return writer.build();
288 }
289 
291 {
293  {
294  // format
296  format << asJson();
297  writer << std::make_pair("format", format.build());
298  }
299  {
300  // video streams
302  for(std::vector<avtranscoder::VideoProperties>::const_iterator it = _videoStreams.begin(); it != _videoStreams.end();
303  ++it)
304  {
305  video << it->asJson();
306  }
307  writer << std::make_pair("video", video.build());
308  }
309  {
310  // audio streams
312  for(std::vector<avtranscoder::AudioProperties>::const_iterator it = _audioStreams.begin(); it != _audioStreams.end();
313  ++it)
314  {
315  audio << it->asJson();
316  }
317  writer << std::make_pair("audio", audio.build());
318  }
319  {
320  // data streams
322  for(std::vector<avtranscoder::DataProperties>::const_iterator it = _dataStreams.begin(); it != _dataStreams.end();
323  ++it)
324  {
325  data << it->asJson();
326  }
327  writer << std::make_pair("data", data.build());
328  }
329  {
330  // subtitle streams
332  for(std::vector<avtranscoder::SubtitleProperties>::const_iterator it = _subtitleStreams.begin();
333  it != _subtitleStreams.end(); ++it)
334  {
335  subtitle << it->asJson();
336  }
337  writer << std::make_pair("subtitle", subtitle.build());
338  }
339  {
340  // attachement streams
341  json::JsonArrayStreamWriter attachement;
342  for(std::vector<avtranscoder::AttachementProperties>::const_iterator it = _attachementStreams.begin();
343  it != _attachementStreams.end(); ++it)
344  {
345  attachement << it->asJson();
346  }
347  writer << std::make_pair("attachement", attachement.build());
348  }
349  {
350  // unknown streams
352  for(std::vector<avtranscoder::UnknownProperties>::const_iterator it = _unknownStreams.begin();
353  it != _unknownStreams.end(); ++it)
354  {
355  unknown << it->asJson();
356  }
357  writer << std::make_pair("unknown", unknown.build());
358  }
359  return writer.build();
360 }
361 
363 {
364  _streams.clear();
365 
366  _videoStreams.clear();
367  _audioStreams.clear();
368  _dataStreams.clear();
369  _subtitleStreams.clear();
370  _attachementStreams.clear();
371  _unknownStreams.clear();
372 }
373 
374 std::ostream& operator<<(std::ostream& flux, const FileProperties& fileProperties)
375 {
376  flux << std::left;
377  flux << detail::separator << " Wrapper " << detail::separator << std::endl;
378 
379  PropertyVector properties = fileProperties.asVector();
380  for(PropertyVector::iterator it = properties.begin(); it != properties.end(); ++it)
381  {
382  flux << std::setw(detail::keyWidth) << it->first << ": " << it->second << std::endl;
383  }
384 
385  return flux;
386 }
387 }
size_t getBitRate() const
total stream bitrate in bit/s, 0 if not available (result of a computation by ffmpeg) ...
Base class of Progress. Inherit this class to have your own way to manage a progress bar...
Definition: IProgress.hpp:23
std::vector< std::pair< std::string, std::string > > PropertyVector
PropertyVector is a vector of pair, because the order of properties matters to us.
Definition: util.hpp:23
EAnalyseLevel
Level of file analysis.
Definition: util.hpp:10
std::vector< DataProperties > _dataStreams
Array of properties per data stream.
PropertyMap asMap() const
Return format properties as a map (name of property, value)
bool isRawFormat() const
Is there a container, or a raw bitstreams without access to timing information.
void extractStreamProperties(IProgress &progress, const EAnalyseLevel level)
Relaunch streams analysis with a specific level.
Write an array to a stream.
Definition: JsonWriter.hpp:106
const size_t keyWidth
Definition: util.hpp:32
std::vector< AttachementProperties > _attachementStreams
Array of properties per attachement stream.
const std::string separator
Definition: util.hpp:33
void add(PropertyVector &propertyVector, const std::string &key, const size_t &value)
Definition: util.cpp:16
std::string getFilename() const
size_t getNbSubtitleStreams() const
std::vector< SubtitleProperties > _subtitleStreams
Array of properties per subtitle stream.
void fillMetadataDictionnary(AVDictionary *avdictionnary, PropertyVector &metadata)
Fill metadata parameter with the given AVDictionary.
Definition: util.cpp:55
std::string allPropertiesAsJson() const
Return all properties as a json format.
std::string getFormatLongName() const
Descriptive name for the format, meant to be more human-readable than name, or empty if unknown...
const std::vector< avtranscoder::StreamProperties * > getStreamProperties() const
std::map< size_t, StreamProperties * > _streams
Map of properties per stream index (of all types) - only references to the following properties...
const avtranscoder::StreamProperties & getStreamPropertiesWithIndex(const size_t streamIndex) const
void addProperty(PropertyVector &data, const std::string &key, T(FileProperties::*getter)(void) const) const
std::map< std::string, std::string > PropertyMap
Definition: util.hpp:24
std::string getFormatMimeType() const
Comma-separated list of mime types, or empty if unknown.
std::vector< AudioProperties > _audioStreams
Array of properties per audio stream.
PropertyVector asVector() const
Return format properties as a vector (name of property: value)
Wrapper of an AVFormatContext.
std::string getFormatName() const
A comma separated list of short names for the format, or empty if unknown.
std::vector< UnknownProperties > _unknownStreams
Array of properties per unknown stream.
std::vector< VideoProperties > _videoStreams
Array of properties per video stream.
size_t getNbAttachementStreams() const
Virtual based class of properties for all types of stream.
std::string asJson() const
Return all format properties as a json format.
Write an object to a stream.
Definition: JsonWriter.hpp:84
size_t getNbUnknownStreams() const
std::ostream & operator<<(std::ostream &flux, const InputFile &input)
Definition: InputFile.cpp:171
const AVFormatContext * _avFormatContext
Has link (no ownership)
PropertyVector & fillVector(PropertyVector &data) const
To avoid copy of the vector.
const FormatContext * _formatContext
Has link (no ownership)
float getDuration() const
in seconds
Implementation of IProgress, to manage cases when we need an IProgress but don't care of a progress b...
FileProperties(const FormatContext &formatContext)
Analayse a file from its FormatContext.
AVStream & getAVStream(size_t index) const
void clearStreamProperties()
Clear all array of stream properties.