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 }