File indexing completed on 2024-12-22 04:34:54

0001 /*
0002     SPDX-FileCopyrightText: 2003-2004 Christian Kvasny <chris@k3b.org>
0003     SPDX-FileCopyrightText: 1998-2007 Sebastian Trueg <trueg@k3b.org>
0004 
0005     SPDX-License-Identifier: GPL-2.0-or-later
0006 */
0007 
0008 #include "k3bmpeginfo.h"
0009 #include "k3b_i18n.h"
0010 
0011 #ifdef Q_OS_WIN32
0012 #define ftello ftell
0013 #define fseeko fseek
0014 #endif
0015 
0016 static const double frame_rates[ 16 ] =
0017 {
0018     0.0, 24000.0 / 1001, 24.0, 25.0,
0019     30000.0 / 1001, 30.0, 50.0, 60000.0 / 1001,
0020     60.0, 0.0,
0021 };
0022 
0023 K3b::MpegInfo::MpegInfo( const char* filename )
0024     : m_mpegfile( 0 ),
0025       m_filename( filename ),
0026       m_done( false ),
0027       m_buffstart( 0 ),
0028       m_buffend( 0 ),
0029       m_buffer( 0 ),
0030       m_initial_TS( 0.0 )
0031 {
0032 
0033     mpeg_info = new Mpeginfo();
0034 
0035     m_mpegfile = fopen( filename, "rb" );
0036 
0037     if ( m_mpegfile == 0 ) {
0038         qDebug() << QString( "Unable to open %1" ).arg( m_filename );
0039         return ;
0040     }
0041 
0042     if ( fseeko( m_mpegfile, 0, SEEK_END ) ) {
0043         qDebug() << QString( "Unable to seek in file %1" ).arg( m_filename );
0044         return ;
0045     }
0046 
0047     llong lof = ftello( m_mpegfile );
0048 
0049     if ( lof == -1 ) {
0050         qDebug() << QString( "Seeking to end of input file %1 failed." ).arg( m_filename );
0051         //give up..
0052         return ;
0053     } else
0054         m_filesize = lof;
0055 
0056     // nothing to do on an empty file
0057     if ( !m_filesize ) {
0058         qDebug() << QString( "File %1 is empty." ).arg( m_filename );
0059         m_error_string = i18n( "File %1 is empty." , m_filename );
0060         return ;
0061     }
0062 
0063     m_buffer = new byte[ BUFFERSIZE ];
0064 
0065     MpegParsePacket ( );
0066 
0067 }
0068 
0069 K3b::MpegInfo::~MpegInfo()
0070 {
0071     if ( m_buffer ) {
0072         delete[] m_buffer;
0073     }
0074     if ( m_mpegfile ) {
0075         fclose( m_mpegfile );
0076     }
0077 
0078     delete mpeg_info;
0079 }
0080 
0081 
0082 bool K3b::MpegInfo::MpegParsePacket ()
0083 {
0084 
0085     /* verify the packet begins with a pack header */
0086     if ( !EnsureMPEG( 0, MPEG_PACK_HEADER_CODE ) ) {
0087         llong code = GetNBytes( 0, 4 );
0088 
0089         qDebug() << QString( "(K3b::MpegInfo::mpeg_parse_packet ()) pack header code 0x%1 expected, but 0x%2 found" ).arg( 0x00000100 + MPEG_PACK_HEADER_CODE, 0, 16 ).arg( code, 0, 16 );
0090 
0091         if ( code == 0x00000100 + MPEG_SEQUENCE_CODE ) {
0092             qDebug() << "...this looks like an elementary video stream but a multiplexed program stream was required.";
0093             m_error_string = i18n( "This looks like an elementary video stream but a multiplexed program stream was required." );
0094         }
0095 
0096         if ( ( 0xfff00000 & code ) == 0xfff00000 ) {
0097             qDebug() << "...this looks like an elementary audio stream but a multiplexed program stream was required.";
0098             m_error_string = i18n( "This looks like an elementary audio stream but a multiplexed program stream was required." );
0099         }
0100 
0101         if ( code == 0x52494646 ) {
0102             qDebug() << "...this looks like a RIFF header but a plain multiplexed program stream was required.";
0103             m_error_string = i18n( "This looks like a RIFF header but a plain multiplexed program stream was required." );
0104         }
0105 
0106         return false;
0107     }
0108 
0109 
0110     /* take a look at the pack header */
0111     int offset = 0;
0112     while ( GetByte( offset ) == 0x00 )
0113         offset ++;
0114     //here we're on the first non null byte let's get back to leave two zeros (packet start code)
0115     offset -= 2;
0116 
0117     if ( offset != 0 ) {
0118         // we actually skipped some zeroes
0119         qDebug() << QString( "Skipped %1 zeroes at start of file" ).arg( offset );
0120     }
0121 
0122     // here while schleife
0123     while ( offset != -1 ) {
0124         offset = MpegParsePacket( offset );
0125     }
0126 
0127     /*
0128       int pkt = 0;
0129       offset = FindNextMarker( 0, MPEG_PACK_HEADER_CODE );
0130 
0131       while ( offset != -1 ) {
0132       pkt++;
0133       offset = FindNextMarker( offset+1, MPEG_PACK_HEADER_CODE );
0134       }
0135 
0136       qDebug() << "Pkt found: " << pkt;
0137     */
0138 
0139     //seek the file duration by fetching the last PACK
0140     //and reading its timestamp
0141     llong last_pack = bdFindNextMarker( m_filesize - 13, MPEG_PACK_HEADER_CODE );
0142     // -12 because a PACK is at least 12 bytes
0143     double duration;
0144     last_pack += 4;
0145     int bits = GetByte( last_pack ) >> 4;
0146 
0147     if ( bits == 0x2 )                /* %0010 ISO11172-1 */
0148     {
0149         duration = ReadTS( last_pack );
0150     } else if ( bits >> 2 == 0x1 )                /* %01xx ISO13818-1 */
0151     {
0152         duration = ReadTSMpeg2( last_pack );
0153     } else {
0154         qDebug() << QString( "no timestamp found" );
0155         duration = ReadTS( last_pack );
0156     }
0157 
0158     mpeg_info->playing_time = duration - m_initial_TS;
0159 
0160 
0161     if ( !mpeg_info->has_video )
0162         for ( int i = 0; i < 2; i++ )
0163             if ( mpeg_info->video[ i ].seen )
0164                 mpeg_info->has_video = true;
0165 
0166     if ( !mpeg_info->has_audio )
0167         for ( int i = 0; i < 2; i++ )
0168             if ( mpeg_info->audio[ i ].seen )
0169                 mpeg_info->has_audio = true;
0170 
0171     return true;
0172 }
0173 
0174 llong K3b::MpegInfo::MpegParsePacket ( llong offset )
0175 {
0176     byte mark = 0;
0177     uint size = 0;
0178 
0179     /* continue until start code seen */
0180     offset = FindNextMarker( offset, &mark );
0181 
0182     if ( offset < 0 )
0183         return offset;
0184 
0185     switch ( mark ) {
0186         int bits;
0187 
0188     case MPEG_PACK_HEADER_CODE:
0189         // qDebug() << QString( "MPEG_PACK_HEADER_CODE @ %1" ).arg( offset );
0190 
0191         offset += 4;
0192 
0193         if ( mpeg_info->version != MPEG_VERS_INVALID )
0194             break;
0195 
0196         bits = GetByte( offset ) >> 4;
0197 
0198         if ( bits == 0x2 )                /* %0010 ISO11172-1 */
0199         {
0200             mpeg_info->version = MPEG_VERS_MPEG1;
0201 
0202             unsigned long muxrate = 0;
0203 
0204             muxrate = ( GetByte( offset + 5 ) & 0x7F ) << 15;
0205             muxrate |= ( GetByte( offset + 6 ) << 7 );
0206             muxrate |= ( GetByte( offset + 7 ) >> 1 );
0207 
0208             mpeg_info->muxrate = muxrate * 50 * 8;
0209 
0210             if ( m_initial_TS == 0.0 )
0211             {
0212                 m_initial_TS = ReadTS( offset );
0213                 qDebug() << QString( "Initial TS = %1" ).arg( m_initial_TS );
0214             }
0215 
0216         } else if ( bits >> 2 == 0x1 )                /* %01xx ISO13818-1 */
0217         {
0218             mpeg_info->version = MPEG_VERS_MPEG2;
0219 
0220             unsigned long muxrate = 0;
0221             muxrate = GetByte( offset + 6 ) << 14;
0222             muxrate |= GetByte( offset + 7 ) << 6;
0223             muxrate |= GetByte( offset + 8 ) >> 2;
0224 
0225             mpeg_info->muxrate = muxrate * 50 * 8;
0226 
0227             if ( m_initial_TS == 0.0 )
0228             {
0229                 m_initial_TS = ReadTSMpeg2( offset );
0230                 qDebug() << QString( "Initial TS = %1" ).arg( m_initial_TS );
0231             }
0232 
0233         } else {
0234             qDebug() << QString( "packet not recognized as either version 1 or 2 (%1)" ).arg( bits );
0235             mpeg_info->version = MPEG_VERS_INVALID;
0236             return -1;
0237         }
0238         break;
0239 
0240     case MPEG_SYSTEM_HEADER_CODE:
0241     case MPEG_PAD_CODE:
0242     case MPEG_PRIVATE_1_CODE:
0243     case MPEG_VIDEO_E0_CODE:
0244     case MPEG_VIDEO_E1_CODE:
0245     case MPEG_VIDEO_E2_CODE:
0246     case MPEG_AUDIO_C0_CODE:
0247     case MPEG_AUDIO_C1_CODE:
0248     case MPEG_AUDIO_C2_CODE:
0249 
0250         offset += 4;
0251         size = GetSize( offset );
0252         offset += 2;
0253 #ifdef K3B_DEBUG
0254         qDebug() << QString( "offset = %1, size = %2" ).arg( offset ).arg( size );
0255 #endif
0256 
0257         switch ( mark ) {
0258         case MPEG_SYSTEM_HEADER_CODE:
0259             // qDebug() << QString( "Systemheader: %1" ).arg( m_code, 0, 16 );
0260             break;
0261 
0262         case MPEG_VIDEO_E0_CODE:
0263         case MPEG_VIDEO_E1_CODE:
0264         case MPEG_VIDEO_E2_CODE:
0265             ParseVideo( offset, mark );
0266             // _analyze_video_pes (code & 0xff, buf + pos, size, !parse_pes, ctx);
0267             if ( mpeg_info->has_video && mpeg_info->has_audio ) {
0268                 return -1;
0269             } else if ( mark == MPEG_VIDEO_E0_CODE || (mpeg_info->version == MPEG_VERS_MPEG2 && mark == MPEG_VIDEO_E1_CODE) || (mpeg_info->version == MPEG_VERS_MPEG1 && mark == MPEG_VIDEO_E2_CODE) ) {
0270                 mpeg_info->has_video = true;
0271                 offset = FindNextAudio( offset );
0272             }
0273             break;
0274         case MPEG_AUDIO_C0_CODE:
0275         case MPEG_AUDIO_C1_CODE:
0276         case MPEG_AUDIO_C2_CODE:
0277             offset = SkipPacketHeader( offset - 6 );
0278             ParseAudio( offset, mark );
0279             // audio packet doesn't begin with 0xFFF
0280             if (GetAudioIdx(mark) != -1 && !mpeg_info->audio[GetAudioIdx(mark)].seen) {
0281                 int a_idx = GetAudioIdx(mark);
0282                 while ( ( offset < m_filesize - 10 ) && !mpeg_info->audio[ a_idx ].seen ) {
0283                     if ( ( GetByte( offset ) == 0xFF ) && ( GetByte( offset + 1 ) & 0xF0 ) == 0xF0 )
0284                         ParseAudio( offset, mark );
0285                     offset++;
0286                 }
0287             }
0288 
0289             mpeg_info->has_audio = true;
0290             if ( mpeg_info->has_video )
0291                 return -1;
0292 
0293             offset = FindNextVideo( offset );
0294             break;
0295 
0296         case MPEG_PRIVATE_1_CODE:
0297             qDebug() << QString( "PrivateCode: %1" ).arg( mark, 0, 16 );
0298             break;
0299         }
0300         break;
0301 
0302     case MPEG_PROGRAM_END_CODE:
0303         qDebug() << QString( "ProgramEndCode: %1" ).arg( mark, 0, 16 );
0304         offset += 4;
0305         break;
0306 
0307     case MPEG_PICTURE_CODE:
0308         qDebug() << QString( "PictureCode: %1" ).arg( mark, 0, 16 );
0309         offset += 3;
0310         break;
0311 
0312     default:
0313         offset += 4;
0314         break;
0315     }
0316 
0317     return offset;
0318 }
0319 
0320 byte K3b::MpegInfo::GetByte( llong offset )
0321 {
0322     unsigned long nread;
0323     if ( ( offset >= m_buffend ) || ( offset < m_buffstart ) ) {
0324 
0325         if ( fseeko( m_mpegfile, offset, SEEK_SET ) ) {
0326             qDebug() << QString( "could not get seek to offset (%1) in file %2 (size:%3)" ).arg( offset ).arg( m_filename ).arg( m_filesize );
0327             return 0x11;
0328         }
0329         nread = fread( m_buffer, 1, BUFFERSIZE, m_mpegfile );
0330         m_buffstart = offset;
0331         m_buffend = offset + nread;
0332         if ( ( offset >= m_buffend ) || ( offset < m_buffstart ) ) {
0333             // weird
0334             qDebug() << QString( "could not get offset %1 in file %2 [%3]" ).arg( offset ).arg( m_filename ).arg( m_filesize );
0335             return 0x11;
0336         }
0337     }
0338     return m_buffer[ offset - m_buffstart ];
0339 }
0340 
0341 // same as above but improved for backward search
0342 byte K3b::MpegInfo::bdGetByte( llong offset )
0343 {
0344     unsigned long nread;
0345     if ( ( offset >= m_buffend ) || ( offset < m_buffstart ) ) {
0346         llong start = offset - BUFFERSIZE + 1 ;
0347         start = start >= 0 ? start : 0;
0348 
0349         fseeko( m_mpegfile, start, SEEK_SET );
0350 
0351         nread = fread( m_buffer, 1, BUFFERSIZE, m_mpegfile );
0352         m_buffstart = start;
0353         m_buffend = start + nread;
0354         if ( ( offset >= m_buffend ) || ( offset < m_buffstart ) ) {
0355             // weird
0356             qDebug() << QString( "could not get offset %1 in file %2 [%3]" ).arg( offset ).arg( m_filename ).arg( m_filesize );
0357 
0358             return 0x11;
0359         }
0360     }
0361     return m_buffer[ offset - m_buffstart ];
0362 }
0363 
0364 
0365 llong K3b::MpegInfo::GetNBytes( llong offset, int n )
0366 {
0367     llong nbytes = 0;
0368     n--;
0369     for ( int i = 0; i < n; i++ )
0370         ( ( char* ) & nbytes ) [ n - i ] = GetByte( offset + i );
0371 
0372     return nbytes;
0373 
0374 }
0375 
0376 // get a two byte size
0377 unsigned short int K3b::MpegInfo::GetSize( llong offset )
0378 {
0379     return GetByte( offset ) * 256 + GetByte( offset + 1 );
0380     // return GetNBytes( offset, 2 );
0381 
0382 }
0383 
0384 bool K3b::MpegInfo::EnsureMPEG( llong offset, byte mark )
0385 {
0386     if ( ( GetByte( offset ) == 0x00 ) &&
0387          ( GetByte( offset + 1 ) == 0x00 ) &&
0388          ( GetByte( offset + 2 ) == 0x01 ) &&
0389          ( GetByte( offset + 3 ) == mark ) )
0390         return true;
0391     else
0392         return false;
0393 }
0394 
0395 
0396 // find next 0x 00 00 01 xx sequence, returns offset or -1 on err
0397 llong K3b::MpegInfo::FindNextMarker( llong from )
0398 {
0399     llong offset;
0400     for ( offset = from; offset < ( m_filesize - 4 ); offset++ ) {
0401         if (
0402             ( GetByte( offset + 0 ) == 0x00 ) &&
0403             ( GetByte( offset + 1 ) == 0x00 ) &&
0404             ( GetByte( offset + 2 ) == 0x01 ) ) {
0405             return offset;
0406         }
0407     }
0408     return -1;
0409 }
0410 
0411 // find next 0x 00 00 01 xx sequence, returns offset or -1 on err and
0412 // change mark to xx
0413 llong K3b::MpegInfo::FindNextMarker( llong from, byte* mark )
0414 {
0415     llong offset = FindNextMarker( from );
0416     if ( offset >= 0 ) {
0417         *mark = GetByte( offset + 3 );
0418         return offset;
0419     } else {
0420         return -1;
0421     }
0422 }
0423 
0424 // find next 0X00 00 01 mark
0425 llong K3b::MpegInfo::FindNextMarker( llong from, byte mark )
0426 {
0427     llong offset = from;
0428     while ( offset >= 0 ) {
0429         offset = FindNextMarker( offset );
0430         if ( offset < 0 ) {
0431             return -1;
0432         }
0433         if ( EnsureMPEG( offset, mark ) ) {
0434             return offset;
0435         } else
0436             offset++;
0437     }
0438 
0439     //shouldn't be here
0440     return -1;
0441 }
0442 
0443 llong K3b::MpegInfo::bdFindNextMarker( llong from, byte mark )
0444 {
0445     llong offset;
0446     for ( offset = from; offset >= 0; offset-- ) {
0447         if (
0448             ( bdGetByte( offset ) == 0x00 ) &&
0449             ( bdGetByte( offset + 1 ) == 0x00 ) &&
0450             ( bdGetByte( offset + 2 ) == 0x01 ) &&
0451             ( bdGetByte( offset + 3 ) == mark ) ) {
0452             return offset;
0453         }
0454     }
0455     return -1;
0456 }
0457 
0458 llong K3b::MpegInfo::bdFindNextMarker( llong from, byte* mark )
0459 {
0460     llong offset;
0461     for ( offset = from; offset >= 0; offset-- ) {
0462         if ( ( bdGetByte( offset ) == 0x00 ) &&
0463              ( bdGetByte( offset + 1 ) == 0x00 ) &&
0464              ( bdGetByte( offset + 2 ) == 0x01 ) ) {
0465             *mark = bdGetByte( offset + 3 );
0466             return offset;
0467         }
0468     }
0469     return -1;
0470 
0471 }
0472 
0473 llong K3b::MpegInfo::FindNextVideo( llong from )
0474 {
0475     llong offset = from;
0476     while ( offset >= 0 ) {
0477         offset = FindNextMarker( offset );
0478         if ( offset < 0 ) {
0479             return -1;
0480         }
0481         if ( EnsureMPEG( offset, MPEG_VIDEO_E0_CODE ) || EnsureMPEG( offset, MPEG_VIDEO_E1_CODE ) || EnsureMPEG( offset, MPEG_VIDEO_E2_CODE ) ) {
0482             return offset;
0483         } else
0484             offset++;
0485     }
0486 
0487     //shouldn't be here
0488     return -1;
0489 }
0490 
0491 llong K3b::MpegInfo::FindNextAudio( llong from )
0492 {
0493     llong offset = from;
0494     while ( offset >= 0 ) {
0495         offset = FindNextMarker( offset );
0496         if ( offset < 0 ) {
0497             return -1;
0498         }
0499         if ( EnsureMPEG( offset, MPEG_AUDIO_C0_CODE ) || EnsureMPEG( offset, MPEG_AUDIO_C1_CODE ) || EnsureMPEG( offset, MPEG_AUDIO_C2_CODE ) ) {
0500             return offset;
0501         } else
0502             offset++;
0503     }
0504 
0505     return -1;
0506 }
0507 
0508 
0509 int K3b::MpegInfo::GetVideoIdx ( byte marker )
0510 {
0511     switch ( marker ) {
0512     case MPEG_VIDEO_E0_CODE:
0513         return 0;
0514         break;
0515 
0516     case MPEG_VIDEO_E1_CODE:
0517         return 1;
0518         break;
0519 
0520     case MPEG_VIDEO_E2_CODE:
0521         return 2;
0522         break;
0523 
0524     default:
0525         qDebug() << "VideoCode not reached";
0526         break;
0527     }
0528 
0529     return -1;
0530 }
0531 
0532 int K3b::MpegInfo::GetAudioIdx ( byte marker )
0533 {
0534     switch ( marker ) {
0535     case MPEG_AUDIO_C0_CODE:
0536         return 0;
0537         break;
0538 
0539     case MPEG_AUDIO_C1_CODE:
0540         return 1;
0541         break;
0542 
0543     case MPEG_AUDIO_C2_CODE:
0544         return 2;
0545         break;
0546 
0547     default:
0548         qDebug() << "VideoCode not reached";
0549         break;
0550     }
0551 
0552     return -1;
0553 }
0554 
0555 llong K3b::MpegInfo::SkipPacketHeader( llong offset )
0556 {
0557     byte tmp_byte;
0558     if ( mpeg_info->version == MPEG_VERS_MPEG1 ) {
0559         // skip startcode and packet size
0560         offset += 6;
0561         //remove stuffing bytes
0562         tmp_byte = GetByte( offset );
0563         while ( tmp_byte & 0x80 )
0564             tmp_byte = GetByte( ++offset );
0565 
0566         if ( ( tmp_byte & 0xC0 ) == 0x40 )                // next two bits are 01
0567             offset += 2;
0568 
0569         tmp_byte = GetByte( offset );
0570         if ( ( tmp_byte & 0xF0 ) == 0x20 )
0571             offset += 5;
0572         else if ( ( tmp_byte & 0xF0 ) == 0x30 )
0573             offset += 10;
0574         else
0575             offset++;
0576 
0577         return offset;
0578     } else if ( mpeg_info->version == MPEG_VERS_MPEG2 ) {
0579         return ( offset + 9 + GetByte( offset + 8 ) );
0580     } else
0581         return ( offset + 10 );
0582 }
0583 
0584 void K3b::MpegInfo::ParseAudio ( llong offset, byte marker )
0585 {
0586     unsigned brate, srate;
0587     bool mpeg2_5 = false;
0588 
0589     const int a_idx = GetAudioIdx(marker);
0590 
0591     if (a_idx == -1 || mpeg_info->audio[a_idx].seen)   /* we have it already */
0592         return ;
0593 
0594     if ( ( GetByte( offset ) != 0xFF ) || ( ( GetByte( offset + 1 ) & 0xF0 ) != 0xF0 ) ) {
0595         // doesn't start with 12 bits set
0596         if ( ( GetByte( offset ) != 0xFF ) || ( ( GetByte( offset + 1 ) & 0xE0 ) != 0xE0 ) ) {
0597             // doesn't start with 11 bits set
0598             return ;
0599         } else {
0600             // start with 11 bits set
0601             mpeg2_5 = true;
0602         }
0603     }
0604 
0605     // Find mpeg version 1.0 or 2.0
0606     if ( GetByte( offset + 1 ) & 0x08 ) {
0607         if ( !mpeg2_5 )
0608             mpeg_info->audio[ a_idx ].version = 1;
0609         else
0610             return ; // invalid 01 encountered
0611     } else {
0612         if ( !mpeg2_5 )
0613             mpeg_info->audio[ a_idx ].version = 2;
0614         else
0615             mpeg_info->audio[ a_idx ].version = 3; //for mpeg 2.5
0616     }
0617 
0618     // Find Layer
0619     mpeg_info->audio[ a_idx ].layer = ( GetByte( offset + 1 ) & 0x06 ) >> 1;
0620     switch ( mpeg_info->audio[ a_idx ].layer ) {
0621     case 0:
0622         mpeg_info->audio[ a_idx ].layer = 0;
0623         break;
0624     case 1:
0625         mpeg_info->audio[ a_idx ].layer = 3;
0626         break;
0627     case 2:
0628         mpeg_info->audio[ a_idx ].layer = 2;
0629         break;
0630     case 3:
0631         mpeg_info->audio[ a_idx ].layer = 1;
0632         break;
0633     }
0634 
0635     // Protection Bit
0636     mpeg_info->audio[ a_idx ].protect = GetByte( offset + 1 ) & 0x01;
0637     if ( mpeg_info->audio[ a_idx ].protect )
0638         mpeg_info->audio[ a_idx ].protect = 0;
0639     else
0640         mpeg_info->audio[ a_idx ].protect = 1;
0641 
0642     const unsigned bit_rates[ 4 ][ 16 ] = {
0643         {
0644             0,
0645         },
0646         {0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 0},
0647         {0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 0},
0648         {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 0}
0649     };
0650 
0651 
0652     /*  const unsigned bit_rates [ 3 ][ 3 ][ 16 ] = {
0653         {
0654         {0, },
0655         {0, },
0656         {0, },
0657         },
0658         {
0659         {0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 0},
0660         {0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 0},
0661         {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 0}
0662         },
0663         {
0664         {0, 32, 48, 56, 64, 80 , 96 , 112, 128, 144, 160, 176, 192, 224, 256, 0},
0665         {0, 8, 16, 24, 32, 40, 48, 56, 64 , 80 , 96 , 112, 128, 144, 160, 0},
0666         {0, 8, 16, 24, 32, 40, 48, 56, 64 , 80 , 96 , 112, 128, 144, 160, 0}
0667         }
0668         };
0669     */
0670 
0671     const unsigned sampling_rates[ 4 ][ 4 ] = {
0672         {
0673             0,
0674         },
0675         {44100, 48000, 32000, 0},                //mpeg 1
0676         {22050, 24000, 16000, 0},                //mpeg 2
0677         {11025, 12000, 8000, 0}   //mpeg 2.5
0678     };
0679 
0680 
0681     // Bitrate index and sampling index to pass through the array
0682     brate = GetByte( offset + 2 ) >> 4;
0683     srate = ( GetByte( offset + 2 ) & 0x0f ) >> 2;
0684 
0685     mpeg_info->audio[ a_idx ].bitrate = 1024 * bit_rates[ mpeg_info->audio[ a_idx ].layer ][ brate ];
0686     mpeg_info->audio[ a_idx ].byterate = ( float ) ( mpeg_info->audio[ a_idx ].bitrate / 8.0 );
0687     mpeg_info->audio[ a_idx ].sampfreq = sampling_rates[ mpeg_info->audio[ a_idx ].version ][ srate ];
0688 
0689     // Audio mode
0690     mpeg_info->audio[ a_idx ].mode = 1 + ( GetByte( offset + 3 ) >> 6 ) ;
0691 
0692     // Copyright bit
0693     if ( GetByte( offset + 3 ) & 0x08 )
0694         mpeg_info->audio[ a_idx ].copyright = true;
0695     else
0696         mpeg_info->audio[ a_idx ].copyright = false;
0697 
0698     // Original/Copy bit
0699     if ( GetByte( offset + 3 ) & 0x04 )
0700         mpeg_info->audio[ a_idx ].original = true;
0701     else
0702         mpeg_info->audio[ a_idx ].original = false;
0703 
0704 
0705     mpeg_info->audio[ a_idx ].seen = true;
0706 }
0707 
0708 void K3b::MpegInfo::ParseVideo ( llong offset, byte marker )
0709 {
0710     unsigned long aratio, frate, brate;
0711 
0712     const int v_idx = GetVideoIdx(marker);
0713 
0714     const double aspect_ratios[ 16 ] = {
0715         0.0000, 1.0000, 0.6735, 0.7031,
0716         0.7615, 0.8055, 0.8437, 0.8935,
0717         0.9375, 0.9815, 1.0255, 1.0695,
0718         1.1250, 1.1575, 1.2015, 0.0000
0719     };
0720 
0721     if (v_idx == -1 || mpeg_info->video[v_idx].seen)   /* we have it already */
0722         return ;
0723 
0724     offset = FindNextMarker( offset + 1, MPEG_SEQUENCE_CODE );
0725 
0726     if ( !offset )
0727         return ;
0728 
0729     offset += 4;
0730 
0731     mpeg_info->video[ v_idx ].hsize = GetSize( offset ) >> 4;
0732     mpeg_info->video[ v_idx ].vsize = GetSize( offset + 1 ) & 0x0FFF;
0733 
0734     // Get picture rate
0735     offset += 3; // after picture sizes
0736 
0737     aratio = ( GetByte( offset ) & 0x0F ) >> 4;
0738     mpeg_info->video[ v_idx ].aratio = aspect_ratios[ aratio ];
0739 
0740     //    offset += 3; // after picture sizes
0741     frate = GetByte( offset ) & 0x0F;
0742     mpeg_info->video[ v_idx ].frate = frame_rates[ frate ];
0743 
0744     offset += 1; // after picture rate
0745 
0746     // 18 following bytes are the bitrate /400
0747 
0748     //read first 16 bytes
0749     brate = GetSize( offset );
0750     // scale
0751     brate <<= 2;
0752     byte lasttwo = GetByte( offset + 2 );
0753     lasttwo >>= 6;
0754     brate |= lasttwo;
0755 
0756     mpeg_info->video[ v_idx ].bitrate = 400 * brate;
0757 
0758     byte mark = -1;
0759     while ( true ) {
0760         offset = FindNextMarker( offset, &mark );
0761         if ( mark == MPEG_GOP_CODE )
0762             break;
0763         switch ( GetByte( offset + 3 ) ) {
0764         case MPEG_EXT_CODE :
0765             // Extension
0766             offset += 4;
0767             switch ( GetByte( offset ) >> 4 ) {
0768             case 1:
0769                 //SequenceExt
0770                 if ( GetByte( offset + 1 ) & 0x08 )
0771                     mpeg_info->video[ v_idx ].progressive = true;
0772                 mpeg_info->video[ v_idx ].chroma_format = ( GetByte( offset + 1 ) & 0x06 ) >> 1;
0773                 break;
0774             case 2:
0775                 // SequenceDisplayExt
0776                 mpeg_info->video[ v_idx ].video_format = ( GetByte( offset ) & 0x0E ) >> 1;
0777                 break;
0778             }
0779 
0780             break;
0781         case MPEG_USER_CODE :
0782             // UserData
0783             break;
0784         }
0785         offset++;
0786     }
0787 
0788     mpeg_info->video[ v_idx ].seen = true;
0789 }
0790 
0791 double K3b::MpegInfo::ReadTS( llong offset )
0792 {
0793     byte highbit;
0794     unsigned long low4Bytes;
0795     double TS;
0796 
0797     highbit = ( GetByte( offset ) >> 3 ) & 0x01;
0798 
0799     low4Bytes = ( ( GetByte( offset ) >> 1 ) & 0x03 ) << 30;
0800     low4Bytes |= GetByte( offset + 1 ) << 22;
0801     low4Bytes |= ( GetByte( offset + 2 ) >> 1 ) << 15;
0802     low4Bytes |= GetByte( offset + 3 ) << 7;
0803     low4Bytes |= GetByte( offset + 4 ) >> 1;
0804 
0805 
0806     TS = ( double ) ( highbit * FLOAT_0x10000 * FLOAT_0x10000 );
0807     TS += ( double ) ( low4Bytes );
0808     TS /= ( double ) ( STD_SYSTEM_CLOCK_FREQ );
0809 
0810     return TS;
0811 }
0812 
0813 double K3b::MpegInfo::ReadTSMpeg2( llong offset )
0814 {
0815     byte highbit;
0816     unsigned long low4Bytes;
0817     unsigned long sys_clock_ref;
0818     double TS;
0819 
0820     highbit = ( GetByte( offset ) & 0x20 ) >> 5;
0821 
0822     low4Bytes = ( ( GetByte( offset ) & 0x18 ) >> 3 ) << 30;
0823     low4Bytes |= ( GetByte( offset ) & 0x03 ) << 28;
0824     low4Bytes |= GetByte( offset + 1 ) << 20;
0825     low4Bytes |= ( GetByte( offset + 2 ) & 0xF8 ) << 12;
0826     low4Bytes |= ( GetByte( offset + 2 ) & 0x03 ) << 13;
0827     low4Bytes |= GetByte( offset + 3 ) << 5;
0828     low4Bytes |= ( GetByte( offset + 4 ) ) >> 3;
0829 
0830     sys_clock_ref = ( GetByte( offset + 4 ) & 0x3 ) << 7;
0831     sys_clock_ref |= ( GetByte( offset + 5 ) >> 1 );
0832 
0833     TS = ( double ) ( highbit * FLOAT_0x10000 * FLOAT_0x10000 );
0834     TS += ( double ) ( low4Bytes );
0835     if ( sys_clock_ref == 0 )
0836         TS /= ( double ) ( STD_SYSTEM_CLOCK_FREQ );
0837     else {
0838         TS /= ( double ) ( 27000000 / sys_clock_ref );
0839     }
0840 
0841     return TS;
0842 }