Changeset 561 for trunk/src/3rdparty/phonon/ds9/mediaobject.cpp
- 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/ds9/mediaobject.cpp
r2 r561 24 24 #ifndef Q_CC_MSVC 25 25 #include <dshow.h> 26 #endif //Q_CC_MSVC26 #endif 27 27 #include <objbase.h> 28 28 #include <initguid.h> … … 37 37 #include <QtCore/QDebug> 38 38 39 #define TIMER_INTERVAL 16 //... ms for the timer that polls the current state (we use the multimedia timer 39 #define TIMER_INTERVAL 16 //... ms for the timer that polls the current state (we use the multimedia timer) 40 40 #define PRELOAD_TIME 2000 // 2 seconds to load a source 41 41 … … 50 50 //first the definition of the WorkerThread class 51 51 WorkerThread::WorkerThread() 52 : QThread(), m_ currentRenderId(0), m_finished(false), m_currentWorkId(1)52 : QThread(), m_finished(false), m_currentWorkId(1) 53 53 { 54 54 } … … 56 56 WorkerThread::~WorkerThread() 57 57 { 58 }59 60 WorkerThread::Work WorkerThread::dequeueWork()61 {62 QMutexLocker locker(&m_mutex);63 if (m_finished) {64 return Work();65 }66 Work ret = m_queue.dequeue();67 68 //we ensure to have the wait condition in the right state69 if (m_queue.isEmpty()) {70 m_waitCondition.reset();71 } else {72 m_waitCondition.set();73 }74 75 return ret;76 58 } 77 59 … … 89 71 DWORD result = ::WaitForMultipleObjects(count, handles, FALSE, INFINITE); 90 72 if (result == WAIT_OBJECT_0) { 91 if (m_finished) {92 //that's the end if the thread execution93 return;94 }95 96 73 handleTask(); 97 74 } else { … … 181 158 w.graph = Graph(CLSID_FilterGraph, IID_IGraphBuilder); 182 159 w.filter = filter; 160 w.graph->AddFilter(filter, 0); 183 161 w.id = m_currentWorkId++; 184 162 m_queue.enqueue(w); … … 200 178 void WorkerThread::handleTask() 201 179 { 202 const Work w = dequeueWork(); 203 204 if (m_finished) { 205 return; 180 QMutexLocker locker(Backend::directShowMutex); 181 { 182 QMutexLocker locker(&m_mutex); 183 if (m_finished || m_queue.isEmpty()) { 184 return; 185 } 186 187 m_currentWork = m_queue.dequeue(); 188 189 //we ensure to have the wait condition in the right state 190 if (m_queue.isEmpty()) { 191 m_waitCondition.reset(); 192 } else { 193 m_waitCondition.set(); 194 } 206 195 } 207 196 208 197 HRESULT hr = S_OK; 209 198 210 m_currentRender = w.graph; 211 m_currentRenderId = w.id; 212 if (w.task == ReplaceGraph) { 213 QMutexLocker locker(&m_mutex); 214 HANDLE h; 215 199 if (m_currentWork.task == ReplaceGraph) { 216 200 int index = -1; 217 201 for(int i = 0; i < FILTER_COUNT; ++i) { 218 if (m_graphHandle[i].graph == w.oldGraph) {202 if (m_graphHandle[i].graph == m_currentWork.oldGraph) { 219 203 m_graphHandle[i].graph = Graph(); 220 204 index = i; … … 229 213 230 214 //add the new graph 231 if (SUCCEEDED(ComPointer<IMediaEvent>(w.graph, IID_IMediaEvent) 215 HANDLE h; 216 if (SUCCEEDED(ComPointer<IMediaEvent>(m_currentWork.graph, IID_IMediaEvent) 232 217 ->GetEventHandle(reinterpret_cast<OAEVENT*>(&h)))) { 233 m_graphHandle[index].graph = w.graph;218 m_graphHandle[index].graph = m_currentWork.graph; 234 219 m_graphHandle[index].handle = h; 235 220 } 236 } else if ( w.task == Render) {237 if ( w.filter) {221 } else if (m_currentWork.task == Render) { 222 if (m_currentWork.filter) { 238 223 //let's render pins 239 w.graph->AddFilter(w.filter, 0); 240 const QList<OutputPin> outputs = BackendNode::pins(w.filter, PINDIR_OUTPUT); 241 for (int i = 0; i < outputs.count(); ++i) { 242 //blocking call 243 hr = w.graph->Render(outputs.at(i)); 244 if (FAILED(hr)) { 245 break; 246 } 247 } 248 } else if (!w.url.isEmpty()) { 224 const QList<OutputPin> outputs = BackendNode::pins(m_currentWork.filter, PINDIR_OUTPUT); 225 for (int i = 0; SUCCEEDED(hr) && i < outputs.count(); ++i) { 226 hr = m_currentWork.graph->Render(outputs.at(i)); 227 } 228 } else if (!m_currentWork.url.isEmpty()) { 249 229 //let's render a url (blocking call) 250 hr = w.graph->RenderFile(reinterpret_cast<const wchar_t *>(w.url.utf16()), 0);230 hr = m_currentWork.graph->RenderFile(reinterpret_cast<const wchar_t *>(m_currentWork.url.utf16()), 0); 251 231 } 252 232 if (hr != E_ABORT) { 253 emit asyncRenderFinished(w.id, hr, w.graph);254 } 255 } else if ( w.task == Seek) {233 emit asyncRenderFinished(m_currentWork.id, hr, m_currentWork.graph); 234 } 235 } else if (m_currentWork.task == Seek) { 256 236 //that's a seekrequest 257 ComPointer<IMediaSeeking> mediaSeeking( w.graph, IID_IMediaSeeking);258 qint64 newtime = w.time * 10000;237 ComPointer<IMediaSeeking> mediaSeeking(m_currentWork.graph, IID_IMediaSeeking); 238 qint64 newtime = m_currentWork.time * 10000; 259 239 hr = mediaSeeking->SetPositions(&newtime, AM_SEEKING_AbsolutePositioning, 260 240 0, AM_SEEKING_NoPositioning); 261 qint64 currentTime = -1; 262 if (SUCCEEDED(hr)) { 263 hr = mediaSeeking->GetCurrentPosition(¤tTime); 264 if (SUCCEEDED(hr)) { 265 currentTime /= 10000; //convert to ms 266 } 267 } 268 emit asyncSeekingFinished(w.id, currentTime); 269 hr = E_ABORT; //to avoid emitting asyncRenderFinished 270 } else if (w.task == ChangeState) { 241 emit asyncSeekingFinished(m_currentWork.id, newtime / 10000); 242 hr = E_ABORT; //to avoid emitting asyncRenderFinished 243 } else if (m_currentWork.task == ChangeState) { 271 244 272 245 //remove useless decoders 273 246 QList<Filter> unused; 274 for (int i = 0; i < w.decoders.count(); ++i) {275 const Filter &filter = w.decoders.at(i);247 for (int i = 0; i < m_currentWork.decoders.count(); ++i) { 248 const Filter &filter = m_currentWork.decoders.at(i); 276 249 bool used = false; 277 250 const QList<OutputPin> pins = BackendNode::pins(filter, PINDIR_OUTPUT); … … 290 263 for (int i = 0; i < unused.count(); ++i) { 291 264 //we should remove this filter from the graph 292 w.graph->RemoveFilter(unused.at(i));265 m_currentWork.graph->RemoveFilter(unused.at(i)); 293 266 } 294 267 295 268 296 269 //we can get the state 297 ComPointer<IMediaControl> mc( w.graph, IID_IMediaControl);270 ComPointer<IMediaControl> mc(m_currentWork.graph, IID_IMediaControl); 298 271 299 272 //we change the state here 300 switch( w.state)273 switch(m_currentWork.state) 301 274 { 302 275 case State_Stopped: … … 316 289 if (SUCCEEDED(hr)) { 317 290 if (s == State_Stopped) { 318 emit stateReady( w.graph, Phonon::StoppedState);291 emit stateReady(m_currentWork.graph, Phonon::StoppedState); 319 292 } else if (s == State_Paused) { 320 emit stateReady( w.graph, Phonon::PausedState);293 emit stateReady(m_currentWork.graph, Phonon::PausedState); 321 294 } else /*if (s == State_Running)*/ { 322 emit stateReady(w.graph, Phonon::PlayingState); 323 } 324 } 325 } 326 327 m_currentRender = Graph(); 328 m_currentRenderId = 0; 329 330 } 331 332 void WorkerThread::abortCurrentRender(qint16 renderId) 333 { 295 emit stateReady(m_currentWork.graph, Phonon::PlayingState); 296 } 297 } 298 } 299 300 { 301 QMutexLocker locker(&m_mutex); 302 m_currentWork = Work(); //reinitialize 303 } 304 } 305 306 void WorkerThread::abortCurrentRender(qint16 renderId) 307 { 334 308 QMutexLocker locker(&m_mutex); 309 if (m_currentWork.id == renderId) { 310 m_currentWork.graph->Abort(); 311 } 335 312 bool found = false; 336 //we try to see if there is already an attempt to seek and we remove it337 313 for(int i = 0; !found && i < m_queue.size(); ++i) { 338 314 const Work &w = m_queue.at(i); … … 340 316 found = true; 341 317 m_queue.removeAt(i); 342 } 343 } 344 345 if (m_currentRender && m_currentRenderId == renderId) { 346 m_currentRender->Abort(); 347 } 348 } 318 if (m_queue.isEmpty()) { 319 m_waitCondition.reset(); 320 } 321 } 322 } 323 } 349 324 350 325 //tells the thread to stop processing … … 353 328 QMutexLocker locker(&m_mutex); 354 329 m_queue.clear(); 355 if (m_current Render) {330 if (m_currentWork.graph) { 356 331 //in case we're currently rendering something 357 m_current Render->Abort();332 m_currentWork.graph->Abort(); 358 333 359 334 } … … 384 359 385 360 for(int i = 0; i < FILTER_COUNT; ++i) { 386 m_graphs[i] = new MediaGraph(this, i); 387 } 388 389 connect(&m_thread, SIGNAL(stateReady(Graph, Phonon::State)),390 SLOT(slotStateReady(Graph, 391 392 connect(&m_thread, SIGNAL(eventReady(Graph, long, long)),393 SLOT(handleEvents(Graph, long,long)));394 395 connect(&m_thread, SIGNAL(asyncRenderFinished(quint16, HRESULT,Graph)),396 SLOT(finishLoading(quint16, HRESULT,Graph)));397 398 connect(&m_thread, SIGNAL(asyncSeekingFinished(quint16, 399 SLOT(finishSeeking(quint16, 361 m_graphs[i] = new MediaGraph(this, i); 362 } 363 364 connect(&m_thread, SIGNAL(stateReady(Graph,Phonon::State)), 365 SLOT(slotStateReady(Graph,Phonon::State))); 366 367 connect(&m_thread, SIGNAL(eventReady(Graph,long,long)), 368 SLOT(handleEvents(Graph,long,long))); 369 370 connect(&m_thread, SIGNAL(asyncRenderFinished(quint16,HRESULT,Graph)), 371 SLOT(finishLoading(quint16,HRESULT,Graph))); 372 373 connect(&m_thread, SIGNAL(asyncSeekingFinished(quint16,qint64)), 374 SLOT(finishSeeking(quint16,qint64))); 400 375 //really special case 401 376 m_mediaObject = this; … … 485 460 486 461 if (!m_aboutToFinishSent && remaining < PRELOAD_TIME - m_transitionTime + TIMER_INTERVAL/2) { 487 //let's take a 2 seconds time t ime to actually load the next file462 //let's take a 2 seconds time to actually load the next file 488 463 #ifdef GRAPH_DEBUG 489 464 qDebug() << "DS9: emit aboutToFinish" << remaining << QTime::currentTime().toString(); … … 520 495 qSwap(m_graphs[0], m_graphs[1]); //swap the graphs 521 496 497 if (m_transitionTime >= 0) 498 m_graphs[1]->stop(); //make sure we stop the previous graph 499 500 if (currentGraph()->mediaSource().type() != Phonon::MediaSource::Invalid && 501 catchComError(currentGraph()->renderResult())) { 502 setState(Phonon::ErrorState); 503 return; 504 } 505 506 //we need to play the next media 507 play(); 508 522 509 //we tell the video widgets to switch now to the new source 523 510 #ifndef QT_NO_PHONON_VIDEO … … 528 515 529 516 emit currentSourceChanged(currentGraph()->mediaSource()); 530 531 if (currentGraph()->isLoading()) {532 //will simply tell that when loading is finished533 //it should start the playback534 play();535 }536 537 538 539 517 emit metaDataChanged(currentGraph()->metadata()); 540 518 … … 549 527 setTitles(currentGraph()->titles()); 550 528 #endif //QT_NO_PHONON_MEDIACONTROLLER 551 552 //this manages only gapless transitions553 if (currentGraph()->mediaSource().type() != Phonon::MediaSource::Invalid) {554 if (catchComError(currentGraph()->renderResult())) {555 setState(Phonon::ErrorState);556 } else {557 play();558 }559 }560 529 } 561 530 … … 583 552 #ifndef QT_NO_PHONON_MEDIACONTROLLER 584 553 //1st, check if there is more titles after 585 const qint64 ret = (m_currentTitle < _iface_availableTitles() - 1) ? 554 const qint64 ret = (m_currentTitle < _iface_availableTitles() - 1) ? 586 555 titleAbsolutePosition(m_currentTitle+1) : currentGraph()->absoluteTotalTime(); 587 556 … … 596 565 { 597 566 //this handles inaccuracy when stopping on a title 598 return currentGraph()->absoluteCurrentTime() 567 return currentGraph()->absoluteCurrentTime() 599 568 #ifndef QT_NO_PHONON_MEDIACONTROLLER 600 569 - titleAbsolutePosition(m_currentTitle) … … 746 715 setState(Phonon::LoadingState); 747 716 //After loading we go into stopped state 748 m_nextState = Phonon::StoppedState; 717 m_nextState = Phonon::StoppedState; 749 718 catchComError(currentGraph()->loadSource(source)); 750 719 emit currentSourceChanged(source); … … 760 729 void MediaObject::loadingFinished(MediaGraph *mg) 761 730 { 762 if (mg == currentGraph()) { 731 if (mg == currentGraph()) { 763 732 #ifndef QT_NO_PHONON_MEDIACONTROLLER 764 733 //Title interface … … 791 760 case Phonon::PausedState: 792 761 pause(); 793 break;794 case Phonon::StoppedState:795 stop();796 762 break; 797 763 case Phonon::PlayingState: … … 801 767 setState(Phonon::ErrorState); 802 768 break; 769 case Phonon::StoppedState: 770 default: 771 stop(); 772 break; 803 773 } 804 774 } … … 817 787 void MediaObject::seekingFinished(MediaGraph *mg) 818 788 { 819 if (mg == currentGraph()) { 789 if (mg == currentGraph()) { 820 790 821 791 updateTargetTick(); … … 848 818 LPAMGETERRORTEXT getErrorText = (LPAMGETERRORTEXT)QLibrary::resolve(QLatin1String("quartz"), "AMGetErrorTextW"); 849 819 850 ushortbuffer[MAX_ERROR_TEXT_LEN];851 if (getErrorText && getErrorText(hr, (WCHAR*)buffer, MAX_ERROR_TEXT_LEN)) {852 m_errorString = QString::from Utf16(buffer);820 WCHAR buffer[MAX_ERROR_TEXT_LEN]; 821 if (getErrorText && getErrorText(hr, buffer, MAX_ERROR_TEXT_LEN)) { 822 m_errorString = QString::fromWCharArray(buffer); 853 823 } else { 854 824 m_errorString = QString::fromLatin1("Unknown error"); … … 892 862 if (VideoWidget *video = qobject_cast<VideoWidget*>(sink)) { 893 863 m_videoWidgets += video; 894 } else 864 } else 895 865 #endif //QT_NO_PHONON_VIDEO 896 866 if (AudioOutput *audio = qobject_cast<AudioOutput*>(sink)) { … … 911 881 if (VideoWidget *video = qobject_cast<VideoWidget*>(sink)) { 912 882 m_videoWidgets.removeOne(video); 913 } else 883 } else 914 884 #endif //QT_NO_PHONON_VIDEO 915 885 if (AudioOutput *audio = qobject_cast<AudioOutput*>(sink)) { … … 993 963 } 994 964 break; 995 case EC_LENGTH_CHANGED: 965 case EC_LENGTH_CHANGED: 996 966 if (graph == currentGraph()->graph()) { 997 967 emit totalTimeChanged( totalTime() );
Note:
See TracChangeset
for help on using the changeset viewer.