2015-04-22 19:22:01 +02:00
# include "mpegaudioframestream.h"
# include "../exceptions.h"
# include "../mediaformat.h"
# include <sstream>
using namespace std ;
using namespace IoUtilities ;
using namespace ConversionUtilities ;
using namespace ChronoUtilities ;
namespace Media {
/*!
* \ class Media : : MpegAudioFrameStream
* \ brief Implementation of Media : : AbstractTrack for a stream of
* MPEG audio frames ( run - of - the - mill MP3 file ) .
*/
/*!
* \ brief Constructs a new track for the \ a stream at the specified \ a startOffset .
*/
MpegAudioFrameStream : : MpegAudioFrameStream ( iostream & stream , uint64 startOffset ) :
AbstractTrack ( stream , startOffset )
{
2015-06-07 00:18:28 +02:00
m_mediaType = MediaType : : Audio ;
2015-04-22 19:22:01 +02:00
}
/*!
* \ brief Destroys the track .
*/
MpegAudioFrameStream : : ~ MpegAudioFrameStream ( )
{ }
TrackType MpegAudioFrameStream : : type ( ) const
{
return TrackType : : MpegAudioFrameStream ;
}
2015-06-10 01:28:22 +02:00
/*!
* \ brief Adds the information from the specified \ a frame to the specified \ a track .
*/
void MpegAudioFrameStream : : addInfo ( const MpegAudioFrame & frame , AbstractTrack & track )
{
track . m_version = frame . mpegVersion ( ) ;
track . m_format = MediaFormat ( GeneralMediaFormat : : Mpeg1Audio , frame . layer ( ) ) ;
track . m_channelCount = frame . channelMode ( ) = = MpegChannelMode : : SingleChannel ? 1 : 2 ;
track . m_sampleRate = frame . samperate ( ) ;
}
2015-04-22 19:22:01 +02:00
void MpegAudioFrameStream : : internalParseHeader ( )
{
2015-06-10 01:28:22 +02:00
static const string context ( " parsing MPEG audio frame header " ) ;
2015-04-22 19:22:01 +02:00
if ( ! m_istream ) {
throw NoDataFoundException ( ) ;
}
// get size
m_istream - > seekg ( - 128 , ios_base : : end ) ;
if ( m_reader . readUInt24BE ( ) = = 0x544147 ) {
m_size = static_cast < uint64 > ( m_istream - > tellg ( ) ) - 3u - m_startOffset ;
} else {
m_size = static_cast < uint64 > ( m_istream - > tellg ( ) ) + 125u - m_startOffset ;
}
m_istream - > seekg ( m_startOffset , ios_base : : beg ) ;
// parse frame header
2015-06-10 01:28:22 +02:00
m_frames . emplace_back ( ) ;
MpegAudioFrame & frame = m_frames . back ( ) ;
2015-04-22 19:22:01 +02:00
frame . parseHeader ( * m_istream ) ;
2015-06-10 01:28:22 +02:00
addInfo ( frame , * this ) ;
2015-04-22 19:22:01 +02:00
if ( frame . isXingBytesfieldPresent ( ) ) {
uint32 xingSize = frame . xingBytesfield ( ) ;
2015-06-10 01:28:22 +02:00
if ( m_size & & xingSize ! = m_size ) {
2015-04-22 19:22:01 +02:00
addNotification ( NotificationType : : Warning , " Real length MPEG of audio frames is not equal with value provided by Xing header. The Xing header value will be used. " , context ) ;
m_size = xingSize ;
}
}
m_bitrate = frame . isXingFramefieldPresent ( )
? ( ( static_cast < double > ( m_size ) * 8.0 ) / ( static_cast < double > ( frame . xingFrameCount ( ) * frame . sampleCount ( ) ) / static_cast < double > ( frame . samperate ( ) ) ) / 1024.0 )
: frame . bitrate ( ) ;
m_bytesPerSecond = m_bitrate * 125 ;
m_duration = TimeSpan : : fromSeconds ( static_cast < double > ( m_size ) / ( m_bitrate * 128.0 ) ) ;
}
}