Skip to content

Commit 1804369

Browse files
author
Clement Champetier
committed
properties: defined getBitRate in StreamProperties class
* Get or compute the stream bitrate depending on the stream type. * VideoProperties: no need to override getDuration method.
1 parent c458e33 commit 1804369

File tree

6 files changed

+110
-115
lines changed

6 files changed

+110
-115
lines changed

src/AvTranscoder/properties/AudioProperties.cpp

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -118,20 +118,6 @@ size_t AudioProperties::getNbChannels() const
118118
return _codecContext->channels;
119119
}
120120

121-
size_t AudioProperties::getBitRate() const
122-
{
123-
if(!_codecContext)
124-
throw std::runtime_error("unknown codec context");
125-
126-
// return bit rate of stream
127-
if(_codecContext->bit_rate)
128-
return _codecContext->bit_rate;
129-
130-
// else get computed bit rate from our computation (warning: way to compute bit rate of PCM audio data)
131-
const int bitsPerSample = av_get_bits_per_sample(_codecContext->codec_id); // 0 if unknown for the given codec
132-
return getSampleRate() * getNbChannels() * bitsPerSample;
133-
}
134-
135121
size_t AudioProperties::getNbSamples() const
136122
{
137123
if(!_formatContext)
@@ -159,7 +145,6 @@ PropertyVector& AudioProperties::fillVector(PropertyVector& data) const
159145
addProperty(data, "sampleFormatName", &AudioProperties::getSampleFormatName);
160146
addProperty(data, "sampleFormatLongName", &AudioProperties::getSampleFormatLongName);
161147
addProperty(data, "sampleRate", &AudioProperties::getSampleRate);
162-
addProperty(data, "bitRate", &AudioProperties::getBitRate);
163148
addProperty(data, "nbSamples", &AudioProperties::getNbSamples);
164149
addProperty(data, "nbChannels", &AudioProperties::getNbChannels);
165150
addProperty(data, "channelLayout", &AudioProperties::getChannelLayout);

src/AvTranscoder/properties/AudioProperties.hpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ class AvExport AudioProperties : public StreamProperties
2121

2222
size_t getSampleRate() const;
2323
size_t getNbChannels() const;
24-
size_t getBitRate() const; ///< in bits/s, 0 if unknown
2524
size_t getNbSamples() const;
2625

2726
size_t getTicksPerFrame() const;

src/AvTranscoder/properties/StreamProperties.cpp

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include <AvTranscoder/properties/util.hpp>
44
#include <AvTranscoder/properties/JsonWriter.hpp>
55
#include <AvTranscoder/properties/FileProperties.hpp>
6+
#include <AvTranscoder/data/decoded/Frame.hpp>
67

78
#include <stdexcept>
89

@@ -58,6 +59,99 @@ size_t StreamProperties::getStreamId() const
5859
return _formatContext->streams[_streamIndex]->id;
5960
}
6061

62+
size_t StreamProperties::getBitRate() const
63+
{
64+
if(!_codecContext)
65+
throw std::runtime_error("unknown codec context");
66+
67+
// return bit rate of stream if present or VBR mode
68+
if(_codecContext->bit_rate || _codecContext->rc_max_rate)
69+
return _codecContext->bit_rate;
70+
71+
LOG_WARN("The bitrate of the stream '" << _streamIndex << "' of file '" << _formatContext->filename << "' is unknown.")
72+
73+
const AVMediaType streamType = getStreamType();
74+
75+
// compute audio bitrate
76+
if(streamType == AVMEDIA_TYPE_AUDIO)
77+
{
78+
LOG_INFO("Compute the audio bitrate (suppose PCM audio data).")
79+
80+
// warning: this is the way to compute bit rate of PCM audio data
81+
const int bitsPerSample = av_get_bits_per_sample(_codecContext->codec_id); // 0 if unknown for the given codec
82+
return _codecContext->sample_rate * _codecContext->channels * bitsPerSample;
83+
}
84+
85+
// compute video bitrate
86+
if(streamType == AVMEDIA_TYPE_VIDEO)
87+
{
88+
LOG_INFO("Compute the video bitrate by decoding the first GOP.")
89+
90+
if(!_formatContext || !_codec)
91+
throw std::runtime_error("cannot compute bit rate: unknown format or codec context");
92+
if(!_codecContext->width || !_codecContext->height)
93+
throw std::runtime_error("cannot compute bit rate: invalid frame size");
94+
95+
// discard no frame type when decode
96+
_codecContext->skip_frame = AVDISCARD_NONE;
97+
98+
Frame frame;
99+
AVPacket pkt;
100+
av_init_packet(&pkt);
101+
avcodec_open2(_codecContext, _codec, NULL);
102+
103+
int gotFrame = 0;
104+
size_t nbDecodedFrames = 0;
105+
int gopFramesSize = 0;
106+
int positionOfFirstKeyFrame = -1;
107+
int positionOfLastKeyFrame = -1;
108+
109+
while(!av_read_frame(const_cast<AVFormatContext*>(_formatContext), &pkt))
110+
{
111+
if(pkt.stream_index == (int)_streamIndex)
112+
{
113+
avcodec_decode_video2(_codecContext, &frame.getAVFrame(), &gotFrame, &pkt);
114+
if(gotFrame)
115+
{
116+
// check distance between key frames
117+
AVFrame& avFrame = frame.getAVFrame();
118+
if(avFrame.pict_type == AV_PICTURE_TYPE_I)
119+
{
120+
if(positionOfFirstKeyFrame == -1)
121+
positionOfFirstKeyFrame = nbDecodedFrames;
122+
else
123+
positionOfLastKeyFrame = nbDecodedFrames;
124+
}
125+
++nbDecodedFrames;
126+
127+
// added size of all frames of the same gop
128+
if(positionOfLastKeyFrame == -1)
129+
{
130+
#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(54, 7, 100)
131+
gopFramesSize += frame.getEncodedSize();
132+
#else
133+
gopFramesSize += pkt.size;
134+
#endif
135+
}
136+
}
137+
}
138+
av_free_packet(&pkt);
139+
if(positionOfFirstKeyFrame != -1 && positionOfLastKeyFrame != -1)
140+
break;
141+
}
142+
avcodec_close(_codecContext);
143+
144+
const size_t gopSize = positionOfLastKeyFrame - positionOfFirstKeyFrame;
145+
if(gopSize > 0)
146+
{
147+
const float fps = av_q2d(_formatContext->streams[_streamIndex]->avg_frame_rate);
148+
return (gopFramesSize / gopSize) * 8 * fps;
149+
}
150+
}
151+
152+
return 0;
153+
}
154+
61155
Rational StreamProperties::getTimeBase() const
62156
{
63157
if(!_formatContext)
@@ -70,7 +164,20 @@ float StreamProperties::getDuration() const
70164
const Rational timeBase = getTimeBase();
71165
const size_t duration = _formatContext->streams[_streamIndex]->duration;
72166
if(duration == (size_t)AV_NOPTS_VALUE)
167+
{
168+
LOG_WARN("The duration of the stream '" << _streamIndex << "' of file '" << _formatContext->filename << "' is unknown.")
169+
if(_fileProperties->isRawFormat())
170+
{
171+
LOG_INFO("Get the stream bitrate to compute the duration.")
172+
const size_t bitRate = getBitRate();
173+
if(bitRate)
174+
{
175+
LOG_INFO("Get the file size to compute the duration.")
176+
return _fileProperties->getFileSize() / bitRate * 8;
177+
}
178+
}
73179
return 0;
180+
}
74181
return av_q2d(timeBase) * duration;
75182
}
76183

@@ -136,6 +243,7 @@ PropertyVector& StreamProperties::fillVector(PropertyVector& data) const
136243
{
137244
addProperty(data, "streamId", &StreamProperties::getStreamId);
138245
addProperty(data, "streamIndex", &StreamProperties::getStreamIndex);
246+
addProperty(data, "bitRate", &StreamProperties::getBitRate);
139247
addProperty(data, "timeBase", &StreamProperties::getTimeBase);
140248
addProperty(data, "duration", &StreamProperties::getDuration);
141249
addProperty(data, "codecId", &StreamProperties::getCodecId);

src/AvTranscoder/properties/StreamProperties.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ class AvExport StreamProperties
2020

2121
size_t getStreamIndex() const { return _streamIndex; }
2222
size_t getStreamId() const;
23+
size_t getBitRate() const; ///< in bits/s, 0 if unknown
2324
Rational getTimeBase() const;
2425
float getDuration() const; ///< in seconds, 0 if not available
2526
AVMediaType getStreamType() const;

src/AvTranscoder/properties/VideoProperties.cpp

Lines changed: 1 addition & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -319,76 +319,6 @@ Rational VideoProperties::getDar() const
319319
return dar;
320320
}
321321

322-
size_t VideoProperties::getBitRate() const
323-
{
324-
if(!_codecContext)
325-
throw std::runtime_error("unknown codec context");
326-
// return bit rate of stream if present or VBR mode
327-
if(_codecContext->bit_rate || _codecContext->rc_max_rate)
328-
return _codecContext->bit_rate;
329-
330-
// else compute bit rate from the first GOP
331-
if(!_formatContext || !_codec)
332-
throw std::runtime_error("cannot compute bit rate: unknown format or codec context");
333-
334-
if(!_codecContext->width || !_codecContext->height)
335-
throw std::runtime_error("cannot compute bit rate: invalid frame size");
336-
337-
LOG_WARN("The bitrate of the stream '" << _streamIndex << "' of file '" << _formatContext->filename << "' is unknown.")
338-
LOG_INFO("Decode the first GOP to compute the bitrate.")
339-
340-
// discard no frame type when decode
341-
_codecContext->skip_frame = AVDISCARD_NONE;
342-
343-
Frame frame;
344-
AVPacket pkt;
345-
av_init_packet(&pkt);
346-
avcodec_open2(_codecContext, _codec, NULL);
347-
348-
int gotFrame = 0;
349-
size_t nbDecodedFrames = 0;
350-
int gopFramesSize = 0;
351-
int positionOfFirstKeyFrame = -1;
352-
int positionOfLastKeyFrame = -1;
353-
354-
while(!av_read_frame(const_cast<AVFormatContext*>(_formatContext), &pkt))
355-
{
356-
if(pkt.stream_index == (int)_streamIndex)
357-
{
358-
avcodec_decode_video2(_codecContext, &frame.getAVFrame(), &gotFrame, &pkt);
359-
if(gotFrame)
360-
{
361-
// check distance between key frames
362-
AVFrame& avFrame = frame.getAVFrame();
363-
if(avFrame.pict_type == AV_PICTURE_TYPE_I)
364-
{
365-
if(positionOfFirstKeyFrame == -1)
366-
positionOfFirstKeyFrame = nbDecodedFrames;
367-
else
368-
positionOfLastKeyFrame = nbDecodedFrames;
369-
}
370-
++nbDecodedFrames;
371-
372-
// added size of all frames of the same gop
373-
if(positionOfLastKeyFrame == -1)
374-
{
375-
#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(54, 7, 100)
376-
gopFramesSize += frame.getEncodedSize();
377-
#else
378-
gopFramesSize += pkt.size;
379-
#endif
380-
}
381-
}
382-
}
383-
av_free_packet(&pkt);
384-
if(positionOfFirstKeyFrame != -1 && positionOfLastKeyFrame != -1)
385-
break;
386-
}
387-
388-
const size_t gopSize = positionOfLastKeyFrame - positionOfFirstKeyFrame;
389-
return (gopFramesSize / gopSize) * 8 * getFps();
390-
}
391-
392322
size_t VideoProperties::getMaxBitRate() const
393323
{
394324
if(!_codecContext)
@@ -477,26 +407,6 @@ float VideoProperties::getFps() const
477407
return av_q2d(_formatContext->streams[_streamIndex]->avg_frame_rate);
478408
}
479409

480-
float VideoProperties::getDuration() const
481-
{
482-
const float duration = StreamProperties::getDuration();
483-
if(duration == 0)
484-
{
485-
LOG_WARN("The duration of the stream '" << _streamIndex << "' of file '" << _formatContext->filename << "' is unknown.")
486-
if(_fileProperties->isRawFormat())
487-
{
488-
const size_t bitRate = getBitRate();
489-
if(bitRate)
490-
{
491-
LOG_INFO("Get the file size to compute the duration.")
492-
return _fileProperties->getFileSize() / bitRate * 8;
493-
}
494-
}
495-
return 0;
496-
}
497-
return duration;
498-
}
499-
500410
bool VideoProperties::hasBFrames() const
501411
{
502412
if(!_codecContext)
@@ -601,9 +511,8 @@ PropertyVector& VideoProperties::fillVector(PropertyVector& data) const
601511
addProperty(data, "chromaSampleLocation", &VideoProperties::getChromaSampleLocation);
602512
addProperty(data, "fieldOrder", &VideoProperties::getFieldOrder);
603513
addProperty(data, "fps", &VideoProperties::getFps);
604-
addProperty(data, "nbFrame", &VideoProperties::getNbFrames);
514+
addProperty(data, "nbFrames", &VideoProperties::getNbFrames);
605515
addProperty(data, "ticksPerFrame", &VideoProperties::getTicksPerFrame);
606-
addProperty(data, "bitRate", &VideoProperties::getBitRate);
607516
addProperty(data, "maxBitRate", &VideoProperties::getMaxBitRate);
608517
addProperty(data, "minBitRate", &VideoProperties::getMinBitRate);
609518
addProperty(data, "hasBFrames", &VideoProperties::hasBFrames);

src/AvTranscoder/properties/VideoProperties.hpp

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ class AvExport VideoProperties : public StreamProperties
4040
Rational getSar() const; // sample/pixel aspect ratio
4141
Rational getDar() const; // display aspect ratio
4242

43-
size_t getBitRate() const; ///< in bits/s, 0 if unknown
4443
size_t getMaxBitRate() const;
4544
size_t getMinBitRate() const;
4645
size_t getNbFrames() const; ///< 0 if unknown
@@ -61,12 +60,6 @@ class AvExport VideoProperties : public StreamProperties
6160
*/
6261
float getFps() const;
6362

64-
/**
65-
* @brief Override StreamProperties method.
66-
* @return The stream duration in seconds, 0 if not available
67-
*/
68-
float getDuration() const;
69-
7063
bool hasBFrames() const;
7164
// bool isClosedGop() const;
7265

0 commit comments

Comments
 (0)