Changeset 561 for trunk/src/3rdparty/phonon/qt7/quicktimevideoplayer.mm
- Timestamp:
- Feb 11, 2010, 11:19:06 PM (15 years ago)
- Location:
- trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk
-
Property svn:mergeinfo
set to (toggle deleted branches)
/branches/vendor/nokia/qt/4.6.1 merged eligible /branches/vendor/nokia/qt/current merged eligible /branches/vendor/trolltech/qt/current 3-149
-
Property svn:mergeinfo
set to (toggle deleted branches)
-
trunk/src/3rdparty/phonon/qt7/quicktimevideoplayer.mm
r2 r561 21 21 #include "audiodevice.h" 22 22 #include "quicktimestreamreader.h" 23 #include "quicktimemetadata.h" 23 24 24 25 #include <QtCore/QCoreApplication> … … 53 54 m_state = NoMedia; 54 55 m_mediaSource = MediaSource(); 56 m_metaData = new QuickTimeMetaData(this); 55 57 m_QTMovie = 0; 56 58 m_streamReader = 0; … … 62 64 m_audioEnabled = false; 63 65 m_hasVideo = false; 66 m_staticFps = 0; 64 67 m_playbackRateSat = false; 65 68 m_isDrmProtected = false; … … 68 71 m_primaryRenderingCIImage = 0; 69 72 m_QImagePixelBuffer = 0; 73 m_cachedCVTextureRef = 0; 74 m_folderTracks = 0; 75 m_currentTrack = 0; 70 76 71 77 #ifdef QUICKTIME_C_API_AVAILABLE … … 78 84 QuickTimeVideoPlayer::~QuickTimeVideoPlayer() 79 85 { 80 unsetVideo(); 86 PhononAutoReleasePool pool; 87 unsetCurrentMediaSource(); 88 delete m_metaData; 81 89 [(NSObject*)m_primaryRenderingTarget release]; 82 90 m_primaryRenderingTarget = 0; … … 85 93 CFRelease(m_visualContext); 86 94 #endif 95 } 96 97 void QuickTimeVideoPlayer::releaseImageCache() 98 { 99 if (m_cachedCVTextureRef){ 100 CVOpenGLTextureRelease(m_cachedCVTextureRef); 101 m_cachedCVTextureRef = 0; 102 } 103 m_cachedQImage = QImage(); 87 104 } 88 105 … … 126 143 127 144 QTVisualContextTask(m_visualContext); 128 return QTVisualContextIsNewImageAvailable(m_visualContext, 0); 145 bool changed = QTVisualContextIsNewImageAvailable(m_visualContext, 0); 146 if (changed) 147 releaseImageCache(); 148 return changed; 129 149 130 150 #elif defined(QT_MAC_USE_COCOA) … … 141 161 if (!m_visualContext) 142 162 return 0; 143 CVOpenGLTextureRef texture = 0; 144 OSStatus err = QTVisualContextCopyImageForTime(m_visualContext, 0, 0, &texture); 145 BACKEND_ASSERT3(err == noErr, "Could not copy image for time in QuickTime player", FATAL_ERROR, 0) 146 return texture; 163 if (!m_cachedCVTextureRef){ 164 OSStatus err = QTVisualContextCopyImageForTime(m_visualContext, 0, 0, &m_cachedCVTextureRef); 165 BACKEND_ASSERT3(err == noErr, "Could not copy image for time in QuickTime player", FATAL_ERROR, 0) 166 } 167 return m_cachedCVTextureRef; 147 168 148 169 #else … … 153 174 QImage QuickTimeVideoPlayer::currentFrameAsQImage() 154 175 { 176 if (!m_cachedQImage.isNull()) 177 return m_cachedQImage; 178 155 179 #ifdef QUICKTIME_C_API_AVAILABLE 156 180 QGLContext *prevContext = const_cast<QGLContext *>(QGLContext::currentContext()); … … 182 206 glEnd(); 183 207 184 QImage image = m_QImagePixelBuffer->toImage(); 185 CVOpenGLTextureRelease(texture); 208 m_cachedQImage = m_QImagePixelBuffer->toImage(); 186 209 // Because of QuickTime, m_QImagePixelBuffer->doneCurrent() will fail. 187 210 // So we store, and restore, the context our selves: 188 211 prevContext->makeCurrent(); 189 return image;212 return m_cachedQImage; 190 213 #else 191 214 CIImage *img = (CIImage *)currentFrameAsCIImage(); … … 196 219 CGRect bounds = [img extent]; 197 220 QImage qImg([bitmap bitmapData], bounds.size.width, bounds.size.height, QImage::Format_ARGB32); 198 QImage swapped= qImg.rgbSwapped();221 m_cachedQImage = qImg.rgbSwapped(); 199 222 [bitmap release]; 200 223 [img release]; 201 return swapped;224 return m_cachedQImage; 202 225 #endif 203 226 } … … 251 274 CVOpenGLTextureRef cvImg = currentFrameAsCVTexture(); 252 275 CIImage *img = [[CIImage alloc] initWithCVImageBuffer:cvImg]; 253 CVOpenGLTextureRelease(cvImg); 254 return img; 276 return img; 255 277 #else 256 278 return 0; … … 274 296 int samplesPerPixel = [bitmap samplesPerPixel]; 275 297 if (![bitmap isPlanar] && (samplesPerPixel == 3 || samplesPerPixel == 4)){ 276 glTexImage2D(GL_TEXTURE_RECTANGLE_EXT, 0, 298 glTexImage2D(GL_TEXTURE_RECTANGLE_EXT, 0, 277 299 samplesPerPixel == 4 ? GL_RGBA8 : GL_RGB8, 278 300 [bitmap pixelsWide], [bitmap pixelsHigh], … … 303 325 m_relativeVolume = relativeVolume; 304 326 if (!m_QTMovie || !m_audioEnabled || m_mute) 305 return; 327 return; 306 328 [m_QTMovie setVolume:(m_masterVolume * m_relativeVolume)]; 307 329 } … … 314 336 315 337 // Work-around bug that happends if you set/unset mute 316 // before movie is playing, and audio is not played 338 // before movie is playing, and audio is not played 317 339 // through graph. Then audio is delayed. 318 340 [m_QTMovie setMuted:mute]; … … 327 349 328 350 // Work-around bug that happends if you set/unset mute 329 // before movie is playing, and audio is not played 351 // before movie is playing, and audio is not played 330 352 // through graph. Then audio is delayed. 331 353 [m_QTMovie setMuted:(!enable || m_mute)]; … … 346 368 // The following code will not work for some media codecs that 347 369 // typically mingle audio/video frames (e.g mpeg). 348 CFStringRef idString = PhononCFString::toCFStringRef(AudioDevice::deviceUID(id)); 370 CFStringRef idString = PhononCFString::toCFStringRef(AudioDevice::deviceUID(id)); 349 371 QTAudioContextRef context; 350 372 QTAudioContextCreateForAudioDevice(kCFAllocatorDefault, idString, 0, &context); … … 370 392 saturation += 1; 371 393 394 if (m_brightness == brightness 395 && m_contrast == contrast 396 && m_hue == hue 397 && m_saturation == saturation) 398 return; 399 372 400 m_brightness = brightness; 373 401 m_contrast = contrast; 374 402 m_hue = hue; 375 403 m_saturation = saturation; 376 377 404 #ifdef QUICKTIME_C_API_AVAILABLE 378 405 Float32 value; … … 386 413 SetMovieVisualSaturation([m_QTMovie quickTimeMovie], value, 0); 387 414 #endif 415 releaseImageCache(); 388 416 } 389 417 … … 398 426 } 399 427 400 void QuickTimeVideoPlayer::unset Video()428 void QuickTimeVideoPlayer::unsetCurrentMediaSource() 401 429 { 402 430 if (!m_QTMovie) … … 411 439 m_isDrmProtected = false; 412 440 m_isDrmAuthorized = true; 441 m_hasVideo = false; 442 m_staticFps = 0; 413 443 m_mediaSource = MediaSource(); 444 m_movieCompactDiscPath.clear(); 414 445 [(CIImage *)m_primaryRenderingCIImage release]; 415 446 m_primaryRenderingCIImage = 0; 416 447 delete m_QImagePixelBuffer; 417 448 m_QImagePixelBuffer = 0; 449 releaseImageCache(); 450 [m_folderTracks release]; 451 m_folderTracks = 0; 418 452 } 419 453 … … 525 559 { 526 560 PhononAutoReleasePool pool; 527 unsetVideo(); 561 unsetCurrentMediaSource(); 562 528 563 m_mediaSource = mediaSource; 529 564 if (mediaSource.type() == MediaSource::Empty || mediaSource.type() == MediaSource::Invalid){ … … 531 566 return; 532 567 } 568 533 569 openMovieFromCurrentMediaSource(); 534 570 if (errorOccured()){ 535 unsetVideo(); 536 return; 537 } 538 571 unsetCurrentMediaSource(); 572 return; 573 } 574 575 prepareCurrentMovieForPlayback(); 576 } 577 578 void QuickTimeVideoPlayer::prepareCurrentMovieForPlayback() 579 { 539 580 #ifdef QUICKTIME_C_API_AVAILABLE 540 581 if (m_visualContext) … … 544 585 waitStatePlayable(); 545 586 if (errorOccured()){ 546 unset Video();587 unsetCurrentMediaSource(); 547 588 return; 548 589 } … … 551 592 preRollMovie(); 552 593 if (errorOccured()){ 553 unset Video();594 unsetCurrentMediaSource(); 554 595 return; 555 596 } … … 558 599 m_playbackRate = prefferedPlaybackRate(); 559 600 checkIfVideoAwailable(); 601 calculateStaticFps(); 560 602 enableAudio(m_audioEnabled); 561 603 setMute(m_mute); 562 604 setVolume(m_masterVolume, m_relativeVolume); 605 m_metaData->update(); 563 606 pause(); 564 607 } … … 574 617 break; 575 618 case MediaSource::Disc: 576 CASE_UNSUPPORTED("Could not open media source.", FATAL_ERROR)619 openMovieFromCompactDisc(); 577 620 break; 578 621 case MediaSource::Stream: … … 636 679 // codecs *think* they can decode the stream, and crash... 637 680 #define TryOpenMovieWithCodec(type) gClearError(); \ 638 openMovieFromData(data, "."type); \681 openMovieFromData(data, (char *)"."type); \ 639 682 if (m_QTMovie) return; 640 683 … … 676 719 } 677 720 721 typedef void (*qt_sighandler_t)(int); 722 static void sigtest(int) { 723 qApp->exit(0); 724 } 725 726 void QuickTimeVideoPlayer::openMovieFromCompactDisc() 727 { 728 // Interrupting the application while the device is open 729 // causes the application to hang. So we need to handle 730 // this in a more graceful way: 731 qt_sighandler_t hndl = signal(SIGINT, sigtest); 732 if (hndl) 733 signal(SIGINT, hndl); 734 735 PhononAutoReleasePool pool; 736 NSString *cd = 0; 737 QString devName = m_mediaSource.deviceName(); 738 if (devName.isEmpty()) { 739 cd = pathToCompactDisc(); 740 if (!cd) { 741 SET_ERROR("Could not open media source.", NORMAL_ERROR) 742 return; 743 } 744 m_movieCompactDiscPath = PhononCFString::toQString(reinterpret_cast<CFStringRef>(cd)); 745 } else { 746 if (!QFileInfo(devName).isAbsolute()) 747 devName = QLatin1String("/Volumes/") + devName; 748 cd = [reinterpret_cast<const NSString *>(PhononCFString::toCFStringRef(devName)) autorelease]; 749 if (!isCompactDisc(cd)) { 750 SET_ERROR("Could not open media source.", NORMAL_ERROR) 751 return; 752 } 753 m_movieCompactDiscPath = devName; 754 } 755 756 m_folderTracks = [scanFolder(cd) retain]; 757 setCurrentTrack(0); 758 } 759 760 QString QuickTimeVideoPlayer::movieCompactDiscPath() const 761 { 762 return m_movieCompactDiscPath; 763 } 764 678 765 MediaSource QuickTimeVideoPlayer::mediaSource() const 679 766 { … … 719 806 PhononAutoReleasePool pool; 720 807 return [[m_QTMovie attributeForKey:@"QTMovieTimeScaleAttribute"] longValue]; 808 } 809 810 float QuickTimeVideoPlayer::staticFps() 811 { 812 return m_staticFps; 813 } 814 815 void QuickTimeVideoPlayer::calculateStaticFps() 816 { 817 if (!m_hasVideo){ 818 m_staticFps = 0; 819 return; 820 } 821 822 #ifdef QT_ALLOW_QUICKTIME 823 Boolean isMpeg = false; 824 Track videoTrack = GetMovieIndTrackType([m_QTMovie quickTimeMovie], 1, 825 FOUR_CHAR_CODE('vfrr'), // 'vfrr' means: has frame rate 826 movieTrackCharacteristic | movieTrackEnabledOnly); 827 Media media = GetTrackMedia(videoTrack); 828 MediaHandler mediaH = GetMediaHandler(media); 829 MediaHasCharacteristic(mediaH, FOUR_CHAR_CODE('mpeg'), &isMpeg); 830 831 if (isMpeg){ 832 MHInfoEncodedFrameRateRecord frameRate; 833 Size frameRateSize = sizeof(frameRate); 834 MediaGetPublicInfo(mediaH, kMHInfoEncodedFrameRate, &frameRate, &frameRateSize); 835 m_staticFps = float(Fix2X(frameRate.encodedFrameRate)); 836 } else { 837 Media media = GetTrackMedia(videoTrack); 838 long sampleCount = GetMediaSampleCount(media); 839 TimeValue64 duration = GetMediaDisplayDuration(media); 840 TimeValue64 timeScale = GetMediaTimeScale(media); 841 m_staticFps = float((double)sampleCount * (double)timeScale / (double)duration); 842 } 843 #else 844 m_staticFps = 30.0f; 845 #endif 721 846 } 722 847 … … 951 1076 } 952 1077 1078 QMultiMap<QString, QString> QuickTimeVideoPlayer::metaData() 1079 { 1080 return m_metaData->metaData(); 1081 } 1082 1083 int QuickTimeVideoPlayer::trackCount() const 1084 { 1085 if (!m_folderTracks) 1086 return 0; 1087 return [m_folderTracks count]; 1088 } 1089 1090 int QuickTimeVideoPlayer::currentTrack() const 1091 { 1092 return m_currentTrack; 1093 } 1094 1095 QString QuickTimeVideoPlayer::currentTrackPath() const 1096 { 1097 if (!m_folderTracks) 1098 return QString(); 1099 1100 PhononAutoReleasePool pool; 1101 NSString *trackPath = [m_folderTracks objectAtIndex:m_currentTrack]; 1102 return PhononCFString::toQString(reinterpret_cast<CFStringRef>(trackPath)); 1103 } 1104 1105 NSString* QuickTimeVideoPlayer::pathToCompactDisc() 1106 { 1107 PhononAutoReleasePool pool; 1108 NSArray *devices = [[NSWorkspace sharedWorkspace] mountedRemovableMedia]; 1109 for (unsigned int i=0; i<[devices count]; ++i) { 1110 NSString *dev = [devices objectAtIndex:i]; 1111 if (isCompactDisc(dev)) 1112 return [dev retain]; 1113 } 1114 return 0; 1115 } 1116 1117 bool QuickTimeVideoPlayer::isCompactDisc(NSString *path) 1118 { 1119 PhononAutoReleasePool pool; 1120 NSString *type = [NSString string]; 1121 [[NSWorkspace sharedWorkspace] getFileSystemInfoForPath:path 1122 isRemovable:0 1123 isWritable:0 1124 isUnmountable:0 1125 description:0 1126 type:&type]; 1127 return [type hasPrefix:@"cdd"]; 1128 } 1129 1130 NSArray* QuickTimeVideoPlayer::scanFolder(NSString *path) 1131 { 1132 NSMutableArray *tracks = [NSMutableArray arrayWithCapacity:20]; 1133 if (!path) 1134 return tracks; 1135 1136 NSDirectoryEnumerator *enumerator = [[NSFileManager defaultManager] enumeratorAtPath:path]; 1137 while (NSString *track = [enumerator nextObject]) { 1138 if (![track hasPrefix:@"."]) 1139 [tracks addObject:[path stringByAppendingPathComponent:track]]; 1140 } 1141 return tracks; 1142 } 1143 1144 void QuickTimeVideoPlayer::setCurrentTrack(int track) 1145 { 1146 PhononAutoReleasePool pool; 1147 [m_QTMovie release]; 1148 m_QTMovie = 0; 1149 m_currentTime = 0; 1150 m_currentTrack = track; 1151 1152 if (!m_folderTracks) 1153 return; 1154 if (track < 0 || track >= (int)[m_folderTracks count]) 1155 return; 1156 1157 NSString *trackPath = [m_folderTracks objectAtIndex:track]; 1158 QTDataReference *dataRef = [QTDataReference dataReferenceWithReferenceToFile:trackPath]; 1159 State currentState = m_state; 1160 openMovieFromDataRef(dataRef); 1161 prepareCurrentMovieForPlayback(); 1162 if (currentState == Playing) 1163 play(); 1164 } 1165 953 1166 }} 954 1167
Note:
See TracChangeset
for help on using the changeset viewer.