first commit
This commit is contained in:
189
project/fm_viewer/fav/AVOutput.cpp
Normal file
189
project/fm_viewer/fav/AVOutput.cpp
Normal file
@@ -0,0 +1,189 @@
|
||||
/******************************************************************************
|
||||
QtAV: Multimedia framework based on Qt and FFmpeg
|
||||
Copyright (C) 2012-2016 Wang Bin <wbsecg1@gmail.com>
|
||||
|
||||
* This file is part of QtAV
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
******************************************************************************/
|
||||
|
||||
#include "AVOutput.h"
|
||||
#include "AVOutput_p.h"
|
||||
#include "Filter.h"
|
||||
#include "FilterContext.h"
|
||||
#include "FilterManager.h"
|
||||
#include "OutputSet.h"
|
||||
#include "Logger.h"
|
||||
|
||||
namespace FAV {
|
||||
|
||||
AVOutputPrivate::~AVOutputPrivate() {
|
||||
cond.wakeAll(); //WHY: failed to wake up
|
||||
}
|
||||
|
||||
AVOutput::AVOutput()
|
||||
{
|
||||
}
|
||||
|
||||
AVOutput::AVOutput(AVOutputPrivate &d)
|
||||
:DPTR_INIT(&d)
|
||||
{
|
||||
}
|
||||
|
||||
AVOutput::~AVOutput()
|
||||
{
|
||||
pause(false); //Does not work. cond may still waiting when destroyed
|
||||
detach();
|
||||
DPTR_D(AVOutput);
|
||||
if (d.filter_context) {
|
||||
delete d.filter_context;
|
||||
d.filter_context = 0;
|
||||
}
|
||||
foreach (Filter *f, d.pending_uninstall_filters) {
|
||||
d.filters.removeAll(f);
|
||||
}
|
||||
QList<Filter*>::iterator it = d.filters.begin();
|
||||
while (it != d.filters.end()) {
|
||||
// if not uninstall here, if AVOutput is also an QObject (for example, widget based renderers)
|
||||
// then qobject children filters will be deleted when parent is destroying and call FilterManager::uninstallFilter()
|
||||
// and FilterManager::instance().unregisterFilter(filter, this) too late that AVOutput is almost be destroyed
|
||||
uninstallFilter(*it);
|
||||
// 1 filter has 1 target. so if has output filter in manager, the output is this output
|
||||
/*FilterManager::instance().hasOutputFilter(*it) && */
|
||||
if ((*it)->isOwnedByTarget() && !(*it)->parent())
|
||||
delete *it;
|
||||
++it;
|
||||
}
|
||||
d.filters.clear();
|
||||
}
|
||||
|
||||
bool AVOutput::isAvailable() const
|
||||
{
|
||||
return d_func().available;
|
||||
}
|
||||
|
||||
void AVOutput::pause(bool p)
|
||||
{
|
||||
DPTR_D(AVOutput);
|
||||
if (d.paused == p)
|
||||
return;
|
||||
d.paused = p;
|
||||
}
|
||||
|
||||
bool AVOutput::isPaused() const
|
||||
{
|
||||
return d_func().paused;
|
||||
}
|
||||
|
||||
//TODO: how to call this automatically before write()?
|
||||
bool AVOutput::tryPause()
|
||||
{
|
||||
DPTR_D(AVOutput);
|
||||
if (!d.paused)
|
||||
return false;
|
||||
QMutexLocker lock(&d.mutex);
|
||||
Q_UNUSED(lock);
|
||||
d.cond.wait(&d.mutex);
|
||||
return true;
|
||||
}
|
||||
|
||||
void AVOutput::addOutputSet(OutputSet *set)
|
||||
{
|
||||
d_func().output_sets.append(set);
|
||||
}
|
||||
|
||||
void AVOutput::removeOutputSet(OutputSet *set)
|
||||
{
|
||||
d_func().output_sets.removeAll(set);
|
||||
}
|
||||
|
||||
void AVOutput::attach(OutputSet *set)
|
||||
{
|
||||
set->addOutput(this);
|
||||
}
|
||||
|
||||
void AVOutput::detach(OutputSet *set)
|
||||
{
|
||||
DPTR_D(AVOutput);
|
||||
if (set) {
|
||||
set->removeOutput(this);
|
||||
return;
|
||||
}
|
||||
foreach(OutputSet *set, d.output_sets) {
|
||||
set->removeOutput(this);
|
||||
}
|
||||
}
|
||||
|
||||
QList<Filter*>& AVOutput::filters()
|
||||
{
|
||||
return d_func().filters;
|
||||
}
|
||||
|
||||
void AVOutput::setStatistics(Statistics *statistics)
|
||||
{
|
||||
DPTR_D(AVOutput);
|
||||
d.statistics = statistics;
|
||||
}
|
||||
|
||||
bool AVOutput::installFilter(Filter *filter, int index)
|
||||
{
|
||||
return onInstallFilter(filter, index);
|
||||
}
|
||||
|
||||
bool AVOutput::onInstallFilter(Filter *filter, int index)
|
||||
{
|
||||
if (!FilterManager::instance().registerFilter(filter, this, index)) {
|
||||
return false;
|
||||
}
|
||||
DPTR_D(AVOutput);
|
||||
d.filters = FilterManager::instance().outputFilters(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* FIXME: how to ensure thread safe using mutex etc? for a video filter, both are in main thread.
|
||||
* an audio filter on audio output may be in audio thread
|
||||
*/
|
||||
bool AVOutput::uninstallFilter(Filter *filter)
|
||||
{
|
||||
return onUninstallFilter(filter);
|
||||
}
|
||||
|
||||
bool AVOutput::onUninstallFilter(Filter *filter)
|
||||
{
|
||||
DPTR_D(AVOutput);
|
||||
FilterManager::instance().unregisterFilter(filter, this);
|
||||
d.pending_uninstall_filters.push_back(filter);
|
||||
return true;
|
||||
}
|
||||
|
||||
void AVOutput::hanlePendingTasks()
|
||||
{
|
||||
onHanlePendingTasks();
|
||||
}
|
||||
|
||||
bool AVOutput::onHanlePendingTasks()
|
||||
{
|
||||
DPTR_D(AVOutput);
|
||||
if (d.pending_uninstall_filters.isEmpty())
|
||||
return false;
|
||||
foreach (Filter *filter, d.pending_uninstall_filters) {
|
||||
d.filters.removeAll(filter);
|
||||
}
|
||||
d.pending_uninstall_filters.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
} //namespace FAV
|
||||
Reference in New Issue
Block a user