You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

121 lines
4.0 KiB

/*****************************************************************************
* Ebml_dispatcher.hpp : matroska demuxer
*****************************************************************************
* Copyright (C) 2016 VLC authors, VideoLAN, Videolabs SAS
*
* Authors: Filip Roseen <filip@videolabs.io>
*
* This program 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 program 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 program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#ifndef VLC_MKV_EBML_DISPATCHER_HPP_
#define VLC_MKV_EBML_DISPATCHER_HPP_
#include "dispatcher.hpp"
#include <ebml/EbmlElement.h>
#include <ebml/EbmlId.h>
#include <algorithm>
#include <typeinfo>
#include <vector>
namespace {
struct EbmlProcessorEntry {
typedef void (*EbmlProcessor) (EbmlElement*, void*);
EbmlId const* p_ebmlid;
EbmlProcessor callback;
EbmlProcessorEntry (EbmlId const& id, EbmlProcessor cb)
: p_ebmlid (&id), callback (cb)
{ }
};
bool operator<( EbmlProcessorEntry const& lhs, EbmlProcessorEntry const& rhs )
{
EbmlId const& lid = *lhs.p_ebmlid;
EbmlId const& rid = *rhs.p_ebmlid;
return lid.GetLength() < rid.GetLength() || (
!( rid.GetLength() < lid.GetLength() ) && lid.GetValue() < rid.GetValue()
);
}
class EbmlTypeDispatcher : public Dispatcher<EbmlTypeDispatcher, EbmlProcessorEntry::EbmlProcessor> {
protected:
typedef std::vector<EbmlProcessorEntry> ProcessorContainer;
public:
void insert (EbmlProcessorEntry const& data) {
_processors.push_back (data);
}
void on_create () {
std::sort (_processors.begin(), _processors.end());
}
bool send (EbmlElement * const& element, void* payload) const
{
if ( element == nullptr )
return false;
EbmlProcessorEntry eb(static_cast<EbmlId const&> (*element), NULL);
// --------------------------------------------------------------
// Find the appropriate callback for the received EbmlElement
// --------------------------------------------------------------
auto cit_end = _processors.cend();
auto cit = std::lower_bound(_processors.cbegin(), cit_end, eb);
/* Check that the processor is valid and unique. */
if (cit != cit_end &&
cit->p_ebmlid == eb.p_ebmlid &&
(*cit->p_ebmlid == *eb.p_ebmlid))
{
cit->callback (element, payload);
return true;
}
if (_default_handler == NULL)
return false;
_default_handler (element, payload);
return true;
}
public:
ProcessorContainer _processors;
};
} /* end-of-namespace */
#define EBML_ELEMENT_CASE_DEF(EbmlType_, ClassName_, VariableName_, InitializationExpr_) \
MKV_SWITCH_CASE_DEFINITION( ClassName_, EbmlType_, EbmlElement*, VariableName_, vars, \
InitializationExpr_, static_cast<EbmlType_&> (*data) \
)
#define E_CASE(EbmlType_, VariableName_) \
EBML_ELEMENT_CASE_DEF(EbmlType_, EbmlType_, VariableName_, \
(dispatcher.insert( EbmlProcessorEntry( EBML_ID(EbmlType_), &EbmlType_ ## _callback) ) ) \
)
#define E_CASE_DEFAULT(VariableName_) \
EBML_ELEMENT_CASE_DEF(EbmlElement, ebml_default, VariableName_, \
dispatcher.set_default_handler (&ebml_default_callback) \
)
#endif