[vlc-devel] [PATCHv6] dcp: Creation of access-demux module for DCP

Denis Charmet typx at dinauz.org
Mon Nov 25 23:14:16 CET 2013


Hi again,

First some general remarks:
* You should declare and initialize variables when you need them not at
the beginning of the function.
* Most of the "this->" are not mandatory
* Most of the gotos and b_stop_parse should be return

More details inlined

Le vendredi 22 novembre 2013 à 07:29:46, Nicolas Bertrand a écrit :
 diff --git a/modules/access/dcp/dcpparser.cpp b/modules/access/dcp/dcpparser.cpp
> new file mode 100644
> index 0000000..0b3ca65
> --- /dev/null
> +++ b/modules/access/dcp/dcpparser.cpp
> @@ -0,0 +1,1462 @@
> +/*****************************************************************************
> + * Copyright (C) 2013 VLC authors and VideoLAN
> + *
> + * Authors:
> + *          Nicolas Bertrand <nico at isf.cc>
> + *
> + * 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.
> + *****************************************************************************/
> +
> +/**
> + * @file dcp.cpp
Bad filename
> + * @brief DCP access-demux module for Digital Cinema Packages using asdcp library
> + */
> +#ifdef HAVE_CONFIG_H
> +#include "config.h"
> +#endif
> +
> +/* VLC core API headers */
> +#include <vlc_common.h>
> +//#include <vlc_demux.h>
> +#include <vlc_plugin.h>
> +#include <vlc_xml.h>
> +#include <vlc_url.h>
> +
> +#include <iostream>
> +#include <string>
> +#include <list>
> +#include <vector>
> +
> +#include "dcpparser.h"
> +
> +using namespace std;
> +
> +static int ReadNextNode(xml_reader_t *p_xmlReader, string& p_node) {
> +    const char * c_node;
> +    int i;
> +    i = xml_ReaderNextNode( p_xmlReader, &c_node );
> +    p_node = c_node;
> +    return i;
> +}
> +
> +static int ReadEndNode(xml_reader_t *p_xmlReader, string p_node, int p_type, string &s_value) {
> +    string node;
> +    int type;
> +
> +    if (p_type != XML_READER_STARTELEM)
> +        goto error;
> +
> +    if (( type = ReadNextNode( p_xmlReader, node ) ) > 0) {
> +        if ( type == XML_READER_TEXT ) {
> +            s_value = node;
> +            if (unlikely(node.empty()))
> +                goto error;
> +        } else
> +            goto error;
> +    } else
> +        goto error;
> +
> +    if (( type = ReadNextNode( p_xmlReader, node ) ) > 0) {
> +        if ( type == XML_READER_ENDELEM ) {
> +            if (node != p_node)
> +                goto error;
> +         } else
> +            goto error;
> +    } else
> +        goto error;
This is overly complicated... Don't use goto if your only action is a
return... In any case, your goal seems just to do something like:
if (ReadNextNode(p_xmlReader, node) == XML_READER_TEXT)
{
    s_value = node;
    if((ReadNextNode(p_xmlReader, node) == XML_READER_ENDELEM) &&
       node == p_node)
        return 0;
}
return -1;

> +
> +    return 0;
> +error:
> +    return -1;
> +}
> +
> +typedef enum {
> +    CHUNK_UNKNOWN = 0,
> +    CHUNK_PATH,
> +    CHUNK_VOL_INDEX,
> +    CHUNK_OFFSET,
> +    CHUNK_LENGTH
> +} ChunkTag_t;
> +
> +
> +typedef enum {
> +    ASSET_UNKNOWN = 0,
> +    ASSET_ID,
> +    ASSET_ANNOTATION_TEXT,
> +    ASSET_PACKING_LIST,
> +    ASSET_CHUNK_LIST,
> +    ASSET_HASH,
> +    ASSET_SIZE,
> +    ASSET_TYPE,
> +    ASSET_ORIGINAL_FILENAME
> +} AssetTag_t;
> +
> +
> +typedef enum {
> +    PKL_UNKNOWN = 0,
> +    PKL_ID,
> +    PKL_ISSUE_DATE,
> +    PKL_ISSUER,
> +    PKL_CREATOR,
> +    PKL_ASSET_LIST,
> +    PKL_ANNOTATION_TEXT, /* start of optional tags */
> +    PKL_ICON_ID,
> +    PKL_GROUP_ID,
> +    PKL_SIGNER,
> +    PKL_SIGNATURE,
> +
> +} PKLTag_t;
> +
> +typedef enum {
> +    CPL_UNKNOWN = 0,
> +    CPL_ID,
> +    CPL_ANNOTATION_TEXT,        /* optional */
> +    CPL_ICON_ID,                /* optional */
> +    CPL_ISSUE_DATE,
> +    CPL_ISSUER,                 /* optional */
> +    CPL_CREATOR,                /* optional */
> +    CPL_CONTENT_TITLE,
> +    CPL_CONTENT_KIND,
> +    CPL_CONTENT_VERSION,        /* not optional, but not always present*/
> +    CPL_RATING_LIST,            /* not handled */
> +    CPL_REEL_LIST,
> +    CPL_SIGNER,                 /* optional - not handled */
> +    CPL_SIGNATURE               /* optional - not handled */
> +} CPLTag_t;
> +
> +
> +class ChunkList: public std::list<Chunk> {
> +public :
> +    ChunkList();
> +    ~ChunkList();
> +};
> +
> +/*
> + * Chunk Class
> + */
> +
> +Chunk::Chunk():
         i_vol_index(1), i_offset(0), i_length(0) {}
No need to pull a this->foo.
> + {
> +    this->i_vol_index = 1;
> +    this->i_offset = 0;
> +    this->i_length = 0;
> +
> +}
> +int Chunk::Parse( xml_reader_t *p_xmlReader, string p_node, int p_type){
> +    string node;
> +    int type;
> +    string s_value;
> +    ChunkTag_t chunk_tag = CHUNK_UNKNOWN;
> +
> +    cout << "Chunk::Parse Enter = "<< p_node << endl;
> +    if (p_type != XML_READER_STARTELEM)
> +        goto error;
Once again don't use goto if your only goal is to return an error, just
return it. (I'll skip this part now).
> +    if( p_node != "Chunk")
> +        goto error;
> +    /* loop on Chunks Node */
> +    while( ( type = ReadNextNode( p_xmlReader, node ) ) > 0 ) {
> +        cout << "Chunk::Parse node = "<< node << endl;
> +        switch (type) {
> +            case XML_READER_STARTELEM:
<nitpicking> this could be done in a more compact way with something like
static const string names[] = {"Path", "VolumeIndex", "Offset",
                               "Length"};
chunk_tag = CHUNK_UNKNOWN;
for(ChunkTag_t i = 0; i < CHUNK_LENGTH; i++)
  if( node == names[i])
  {
    chunk_tag = i+1;
    break;
  }
if(chunk_tag == CHUNK_UNKNOWN)
  return -1;
> +                if( node =="Path")
> +                    chunk_tag = CHUNK_PATH;
> +                else if( node =="VolumeIndex")
> +                    chunk_tag = CHUNK_VOL_INDEX;
> +                else if( node =="Offset")
> +                    chunk_tag = CHUNK_OFFSET;
> +                else if( node =="Length")
> +                    chunk_tag = CHUNK_LENGTH;
> +                else {
> +                    chunk_tag = CHUNK_UNKNOWN;
> +                    goto error;
> +                }
> +                break;
> +            case XML_READER_TEXT:
> +                s_value = node;
> +                if (unlikely(node.empty()))
> +                    goto error;
> +                break;
> +            case XML_READER_ENDELEM:
> +                /* Verify if we reach Chuk endelem  */
> +                if ( node == p_node) {
> +                    /* verify path */
> +                    if ( this->s_path.empty() ) {
> +                        cout << "Chunk::Parse No path found" <<endl;
> +                        goto error;
> +                    }
> +                    if ( this->i_vol_index != 1 ) {
> +                        cout << "Chunk::Parse Only TODO: Only one VOLINDEX suported. Patch welcome." <<endl;
> +                        goto error;
> +                    }
> +                    /* end of Chnuk tag parse */
> +                    goto end;
> +                }
> +                switch (chunk_tag) {
then you could reuse the table here (mind
the +/-1 if you want to keep unknown at the zero position.
> +                    case CHUNK_PATH:
> +                        if( node != "Path" )
> +                            goto error;
> +                        this->s_path = s_value;
IMO, you can drop the "this".
> +                        break;
> +                     case CHUNK_VOL_INDEX:
> +                        if( node != "VolumeIndex" )
> +                            goto error;
> +                        this->i_vol_index = atoi(s_value.c_str());
> +                        break;
> +                    case CHUNK_OFFSET:
> +                        if( node != "Offset" )
> +                            goto error;
> +                        this->i_offset = atoi(s_value.c_str());
> +                        break;
> +                    case CHUNK_LENGTH:
> +                        if( node != "Length" )
> +                            goto error;
> +                        this->i_length = atoi(s_value.c_str());
> +                        break;
> +                    case CHUNK_UNKNOWN:
> +                    default:
> +                        cout << "Chunk::Parse Unknow chunk tag" <<endl;
> +                        break;
> +                }
> +                break;
> +        }
> +    }
> +
> +end:
> +    return 0;
> +
> +error:
> +    return -1;
> +
> +
> +}
> +
> +int AssetMap::Parse ( )
> +{
> +    int type = 0;
> +    const char* node = NULL;
> +
> +    CPL *cpl;
> +    Reel *reel;
> +    PKL *pkl;
> +    Asset *test_asset;
> +
> +    AssetList *p_asset_list;
> +    AssetList::iterator iter;
> +
> +    vector<string> pklfiles;
> +    string p_filepath;
> +
> +    /* init XML parser */
> +    if( OpenXml() )
> +    {
> +        msg_Err( p_demux, "Failed to initialize XML parser" );
> +        goto error;
> +    }
> +
> +    /* reading ASSETMAP file to get the asset_list */
> +    msg_Dbg( p_demux, "reading ASSETMAP file..." );
> +    while( ( type = xml_ReaderNextNode( p_xmlReader, &node ) ) > 0 ) {
> +        /* This condition determines if we are in AssetList part or not */
> +        if( ( type == XML_READER_STARTELEM ) && ( strcasecmp( node, "AssetList" ) == 0 ) )
> +        {
> +            p_asset_list =  new AssetList();
Beware of exceptions coming with new
> +            p_dcp->p_asset_list = p_asset_list;
> +            ParseAssetList(p_xmlReader, node, type );
leaks if you have several asset lists, maybe a break?
> +        }
> +    }
> +    if (p_asset_list == NULL) {
> +        msg_Err( p_demux, "Could not find AssetList tag in ASSETMAP" );
> +        goto error;
> +    }
> +
> +    /* Look for PKLs path */
> +    for (iter = p_asset_list->begin(); iter != p_asset_list->end() ; ++iter) {
> +        p_filepath = (*iter)->getPath();
> +        if (p_filepath.empty()) {
> +            msg_Err( p_demux, "No path element for asset" );
> +            continue;
> +        }
> +        /* set an absolute file path */
> +        p_filepath = p_dcp->path + p_filepath;
> +
> +        /* case of packing list */
> +        if ((*iter)->isPackingList()) {
> +            pklfiles.push_back( p_filepath );
if you only need one why bother staying in the loop and using a vector?
> +        }
> +    }
> +
> +    if( pklfiles[0].empty() )
test pklfiles.size() before trying the first element.
> +    {
> +        msg_Err( p_demux, "Could not find PKL file in ASSETMAP" );
> +        goto error;
> +    }
> +
> +    /* Create the first PKL */
> +    pkl = new PKL(p_demux, pklfiles[0], p_asset_list, p_dcp->path);
possible exception
> +    if (pkl->Parse())
> +        goto error;
> +    p_dcp->pkls.push_back( pkl );
> +
> +    /* Now, CPL */
> +    if ( pkl->FindCPLs() <= 0 ) {
> +        msg_Err(p_demux, " No CPL found");
> +        goto error;
> +    }
> +    cpl = pkl->getCPL(0);
> +    if( cpl == NULL ) {
> +        msg_Err(p_demux, " No CPL found");
> +        goto error;
> +    }
> +    cpl->Parse();
> +    reel = cpl->getReel(0);
> +
> +    /* test picture */
> +    test_asset = reel->getTrack(TRACK_PICTURE);
> +    cout << "Video Track: "<< test_asset->getPath() << endl;
> +    p_dcp->videofile = p_dcp->path + test_asset->getPath();
> +    test_asset = reel->getTrack(TRACK_SOUND);
> +    p_dcp->audiofile = p_dcp->path + test_asset->getPath();
> +
> +    /* free memory */
> +    CloseXml();
> +    delete pkl;
smells like double free since you pushed it in p_dcp->pkls
> +    std::cout << "parseAssetmapXML OK "<< std::endl;
> +    return VLC_SUCCESS;
> +
> +error:
> +    std::cout << "Error in parseAssetmapXML"<< std::endl;
> +    CloseXml();
> +    return VLC_EGENERIC;
> +}
> +
> +
> +
> +/*
> + * Asset Class
> + */
> +
> +Asset::Asset()
: b_is_packing_list(false),...
> +{
> +    this->b_is_packing_list = false;
> +    this->s_path =  "toto";
really? That's a waste of memory.
> +    this->ui_size = 0;
> +}
> +
> +int Asset::Parse( xml_reader_t *p_xmlReader, string p_node, int p_type)
> +{
> +    string node;
> +    int type;
> +    string s_value;
> +    AssetTag_t asset_tag = ASSET_UNKNOWN;
> +
> +    cout << "Asset::Parse Enter = "<< p_node << endl;
> +    if (p_type != XML_READER_STARTELEM)
> +        goto error;
> +    if( p_node != "Asset")
> +        goto error;
> +    /* loop on Assets Node */
> +    while( ( type = ReadNextNode( p_xmlReader, node ) ) > 0 ) {
> +        cout << "Asset::Parse node = "<< node << "("<< type<<")"<< endl;
> +        if (xml_ReaderIsEmptyElement( p_xmlReader)) {
> +            cout << node << "is an empty element" <<endl;
> +        }
> +        switch (type) {
> +            case XML_READER_STARTELEM:
maybe the table trick can come in handy.
> +                if( node =="Id")
> +                    asset_tag = ASSET_ID;
> +                else if( node =="AnnotationText")
> +                    asset_tag = ASSET_ANNOTATION_TEXT;
> +                else if( node =="PackingList") {
> +                    asset_tag = ASSET_PACKING_LIST;
> +                    /* case of <PackinkList/> tag, bur not compliant with SMPTE-429-9 2007*/
> +                    if (xml_ReaderIsEmptyElement( p_xmlReader))
> +                        this->b_is_packing_list = true;
> +                    }
> +                else if( node =="ChunkList") {
> +                    asset_tag = ASSET_CHUNK_LIST;
> +                    if ( this->parseChunkList(p_xmlReader, node, type ) )
> +                        goto error;
> +                    this->s_path = this->chunk_vec[0].getPath();
> +                } else {
> +                    asset_tag = ASSET_UNKNOWN;
> +                    goto error;
> +                }
> +                break;
> +            case XML_READER_TEXT:
> +                s_value = node;
> +                if (unlikely(node.empty()))
> +                    goto error;
> +                break;
> +            case XML_READER_ENDELEM:
> +                /*Check Presence of Id and Chunklist, when its present */
> +                if ( node == p_node) {
> +                    if ( this->s_id.empty() ) {
> +                        //msg_Err(this->p_demux, " No Id element found in Asset");
> +                        goto error;
> +                    }
> +                    /* TODO: verification of Chunklist */
> +                    goto end;
> +                }
> +                switch (asset_tag) {
> +                    case ASSET_ID:
> +                        if( node != "Id" )
> +                            goto error;
> +                        this->s_id = s_value;
> +                        break;
> +                    case  ASSET_PACKING_LIST:
> +                        if( node != "PackingList" )
> +                            goto error;
> +                        if ( s_value == "true" )
> +                            this->b_is_packing_list = true;
> +                        break;
> +                    case ASSET_ANNOTATION_TEXT:
> +                        if( node != "AnnotationText" )
> +                            goto error;
> +                        this->s_annotation = s_value;
> +                        break;
> +                    default:
> +                        //msg_Err(this->p_demux,"Unknow end attribute %s",s_value.c_str());
> +                        break;
> +                }
> +        }
> +    }
> +end:
> +    return 0;
> +
> +error:
> +    return -1;
> +}
> +
> +int Asset::ParsePKL( xml_reader_t *p_xmlReader)
> +{
> +    string node;
> +    int type;
> +    string s_value;
> +    AssetTag_t i_tag = ASSET_UNKNOWN;
> +
> +    while( ( type = ReadNextNode( p_xmlReader, node ) ) > 0 ) {
> +        cout << "Asset::ParsePKL node = "<< node << endl;
> +        switch (type) {
> +            case XML_READER_STARTELEM:
same thing.
> +                if( node =="AnnotationText")
> +                    i_tag = ASSET_ANNOTATION_TEXT;
> +                else if( node =="Hash")
> +                    i_tag = ASSET_HASH;
> +                else if( node =="Size")
> +                    i_tag = ASSET_SIZE;
> +                else if( node =="Type")
> +                    i_tag = ASSET_TYPE;
> +                else if( node =="OriginalFileName")
> +                    i_tag = ASSET_ORIGINAL_FILENAME;
> +                else {
> +                    i_tag = ASSET_UNKNOWN;
> +                    goto error;
> +                }
> +                break;
> +            case XML_READER_TEXT:
> +                s_value = node;
> +                if (unlikely(node.empty()))
> +                    goto error;
> +                break;
> +            case XML_READER_ENDELEM:
> +                if (node == "Asset") {
> +                    /* Reach end node of asset */
> +                    if (this->s_hash.empty()) {
> +                        cout << " Hash tag invalid " <<endl;
> +                        goto error;
> +                    }
> +                    if (this->ui_size == 0) {
> +                        cout << " Size tag invalid " <<endl;
> +                        goto error;
> +                    }
> +                    if (this->s_type.empty()) {
> +                        cout << " Type tag invalid " <<endl;
> +                        goto error;
> +                    }
> +                    goto end;
> +                }
> +
> +                switch (i_tag) {
> +                    case ASSET_ANNOTATION_TEXT:
> +                        if ( this->s_annotation.empty() )
> +                            this->s_annotation = s_value;
> +                        else
> +                            this->s_annotation = this->s_annotation + "--" + s_value;
> +                        break;
> +                    case ASSET_HASH:
> +                        this->s_hash = s_value;
> +                        break;
> +                    case ASSET_SIZE:
> +                        this->ui_size = atol(s_value.c_str());
> +                        break;
> +                    case ASSET_TYPE:
> +                        this->s_type = s_value;
> +                        break;
> +                    case ASSET_ORIGINAL_FILENAME:
> +                        this->s_original_filename = s_value;
> +                        break;
> +                    case ASSET_UNKNOWN:
> +                    default:
> +                        cout << __LINE__ << " Unknown asset" <<endl;
> +                        break;
> +                }
> +                break;
> +        }
> +    }
> +end:
> +    return 0;
> +
> +error:
> +    return -1;
> +}
> +
> +void Asset::Dump()
> +{
> +string s_str;
> +
> +cout << "Id              = " << this->s_id << endl;
> +cout << "Path            = " << this->s_path << endl;
> +s_str = this->b_is_packing_list ? "True" : "False";
> +cout << "Is PKL          = " << s_str << endl;
> +cout << "Hash            = " << this->s_hash << endl;
> +cout << "Size            = " << this->ui_size << endl;
> +cout << "Type            = " << this->s_type << endl;
> +cout << "OrignalFileName = " << this->s_original_filename << endl;
> +cout << "AnnotationText  = " << this->s_annotation << endl;
> +
> +}
> +
> +int Asset::parseChunkList( xml_reader_t *p_xmlReader, string p_node, int p_type)
> +{
> +    string node;
> +    int type;
> +    string s_value;
> +    std::vector<Chunk> chunk_vec;
> +    //Chunk chunk;
> +    if (p_type != XML_READER_STARTELEM)
> +        goto error;
> +    if( p_node != "ChunkList" )
> +        goto error;
> +    /* loop on Assets Node */
> +    while( ( type = ReadNextNode( p_xmlReader, node ) ) > 0 ) {
> +        cout << "Asset::parseChunkList node = "<< node << endl;
> +         switch (type) {
> +            case XML_READER_STARTELEM:
> +                {
indentation
> +                Chunk chunk;
> +                if (node != "Chunk" )
> +                    goto error;
> +                if ( chunk.Parse(p_xmlReader, node, type) )
> +                    goto error;
> +                chunk_vec.push_back(chunk);
> +                break;
> +                }
> +            case XML_READER_TEXT:
> +                break;
useless
> +            case XML_READER_ENDELEM:
> +                if ( node == p_node) {
> +                    if (chunk_vec.size() != 1 ) {
> +                        cout << "chunklist of size greater than one not supported" << endl;
> +                        goto error;
> +                        }
> +                    this->chunk_vec = chunk_vec;
> +                    goto end;
> +                }
> +                break;
> +        }
> +    }
> +end:
> +    return 0;
> +
> +error:
> +    return -1;
> +}
> +
> +#if 0
> +list<Asset *> AssetList;
> +int main()
> +{
> +    list<Asset *>::iterator itor;
> +    std::cout << "# creating Asset list :" << std::endl;
> +    Asset *_Asset1 = new Asset();
> +    _Asset1->setId("1234");
> +    AssetList.push_back(_Asset1);
> +    Asset *_Asset2 = new Asset();
> +    _Asset2->setId("5678");
> +    AssetList.push_back(_Asset2);
> +    cout << "Size of asset list = "<<AssetList.size()<<endl;
> +    for (itor=AssetList.begin(); itor != AssetList.end() ; ++itor) {
> +        std::cout << "Id=" << (*itor)->getId() << std::endl;
> +    }
> +}
> +#endif
Maybe remove dead code.
> +
> +
> +int AssetMap::ParseAssetList (xml_reader_t *p_xmlReader, string p_node, int p_type)
> +{
> +    string node;
> +    int type;
> +    Asset *asset;
> +
> +    if (p_type != XML_READER_STARTELEM)
> +        goto error;
> +    if( p_node != "AssetList" )
> +        goto error;
> +    /* loop on AssetList nodes */
> +    while( ( type = ReadNextNode( p_xmlReader, node ) ) > 0 ) {
> +        cout << "AssetList::Parse node = "<< node << endl;
> +        switch (type) {
> +            case XML_READER_STARTELEM:
> +                if (node != "Asset" )
> +                    goto error;
> +                asset = new Asset;
> +                if (asset->Parse(p_xmlReader, node, type)){
> +                    delete asset;
> +                    goto error;
> +                }
> +                p_dcp->p_asset_list->push_back(asset);
> +                break;
> +
> +            case XML_READER_ENDELEM:
> +                if (node == "AssetList" )
> +                    goto end;
> +                break;
> +        }
> +    }
> +
> +end :
> +    return 0;
> +error:
> +    return -1;
> +}
> +
> +Asset * AssetMap::getAssetById(AssetList *asset_list, const string p_id)
> +{
> +    cout <<  "AssetList::getAssetById Enter Id=" << p_id <<endl;
meh cout :(
> +    AssetList::iterator index = asset_list->begin() ;
> +    cout << " size ="<< asset_list->size() <<endl;
> +    while (index != asset_list->end()) {
why not a for?
> +        if ((*index)->getId() == p_id )
> +            return *index;
> +        index++;
> +        }
> +    cout << "No matching asset found with Id" << p_id <<endl;
> +    return NULL;
> +}
> +
> +/*
> + * XmlFile Class
> + */
> +
> +XmlFile::XmlFile(demux_t * p_demux, string s_path)
s_path(s_path)...
> +{
> +    this->s_path      = s_path;
> +    this->p_demux     = p_demux;
> +    this->p_stream    = NULL;
> +    this->p_xml       = NULL;
> +    this->p_xmlReader = NULL;
> +
> +    this->type        = XML_UNKNOWN;
> +    /* convert path to uri */
> +}
> +
> +XmlFile::~XmlFile()
> +{
> +    cout << "destructor in Xml::File" << endl;
> +}
> +
> +int XmlFile::OpenXml()
> +{
> +    char *psz_uri;
> +
> +    this->p_xml = xml_Create( this->p_demux );
> +    if (! this->p_xml) {
> +        return -1;
> +    }
> +    psz_uri = vlc_path2uri( this->s_path.c_str(), "file" );
> +    this->p_stream = stream_UrlNew(this->p_demux, psz_uri );
> +    if( ! this->p_stream ) {
> +        xml_Delete(this->p_xml );
> +        free(psz_uri);
> +        return -1;
> +    }
> +
> +    this->p_xmlReader = xml_ReaderCreate( this->p_xml, this->p_stream);
> +    if( ! this->p_xmlReader ) {
> +        stream_Delete( this->p_stream );
> +        xml_Delete(this->p_xml );
> +        free(psz_uri);
> +        return -1;
> +    }
> +    free(psz_uri);
> +    return 0;
> +}
> +
> +void XmlFile::CloseXml() {
> +    if( this->p_stream )
> +        stream_Delete( this->p_stream );
> +    if( this->p_xmlReader )
> +        xml_ReaderDelete( this->p_xmlReader );
> +    if( this->p_xml )
> +        xml_Delete( this->p_xml );
> +
> +}
> +
> +/*
> + * PKL Class
> + */
> +
> +PKL::PKL(demux_t * p_demux, string s_path, AssetList *_asset_list, string s):
> +    XmlFile(p_demux, s_path), asset_list(_asset_list), s_dcp_path(s)
,type(XML_PKL)
> +{
> +    std::cout << "Initialize PKL "<< s_path << std::endl;
> +    type = XML_PKL;
> +}
> +
> +int PKL::Parse()
> +{
> +    string node;
> +    int type;
> +    string s_value;
> +    PKLTag_t i_tag = PKL_UNKNOWN;
> +    cout << "PKL::Parse Enter  "<< endl;
> +    if (this->OpenXml())
> +        return -1;
> +    /* read 1st node  and verify that is a CPL*/
> +    if ( (type = ReadNextNode(this->p_xmlReader, node)) > 0) {
> +        if ( ! ((type == XML_READER_STARTELEM) && (node == "PackingList")) )    {
> +            msg_Err( this->p_demux, "Not a valid XML Packing List");
> +            goto error;
> +        }
> +    } else {
> +        msg_Err( this->p_demux, "XML read failed");
> +        goto error;
> +    }
> +    while( ( type = ReadNextNode( this->p_xmlReader, node ) ) > 0 ) {
> +        cout << "PKL::Parse node = "<< node << endl;
> +        switch (type) {
> +            case XML_READER_STARTELEM:
table maybe
> +                if( node =="Id")
> +                    i_tag = PKL_ID;
> +                else if( node == "IssueDate")
> +                    i_tag = PKL_ISSUE_DATE;
> +                else if( node == "Issuer")
> +                    i_tag = PKL_ISSUER;
> +                else if( node == "Creator")
> +                    i_tag = PKL_CREATOR;
> +                else if( node == "AssetList") {
> +                    i_tag = PKL_ASSET_LIST;
> +                    if ( this->ParseAssetList(node, type) )
> +                        goto error;
> +                } else if( node == "AnnotationText")
> +                    i_tag = PKL_ANNOTATION_TEXT;
> +                else if( node == "IconId")
> +                    i_tag = PKL_ICON_ID;
> +                else if( node == "GroupId")
> +                    i_tag = PKL_GROUP_ID;
> +                else if( node == "Signer") {
> +                    i_tag = PKL_SIGNER;
> +                    if ( this->ParseSigner(node, type) )
> +                        goto error;
> +                } else if( node == "ds:Signature") {
> +                    i_tag = PKL_SIGNATURE;
> +                    if ( this->ParseSignature(node, type) )
> +                        goto error;
> +                } else {
> +                    i_tag = PKL_UNKNOWN;
> +                    goto error;
> +                }
> +                break;
> +           case XML_READER_TEXT:
> +                s_value = node;
> +                if (unlikely(node.empty()))
> +                    goto error;
> +                break;
> +
> +            case XML_READER_ENDELEM:
> +                switch (i_tag) {
> +                    case PKL_ID:
> +                        if( node != "Id" )
> +                            goto error;
> +                        this->s_id = s_value;
> +                        break;
> +                    case PKL_ISSUE_DATE:
> +                        if( node != "IssueDate" )
> +                            goto error;
> +                        this->s_issue_date= s_value;
> +                        break;
> +                    case PKL_ISSUER:
> +                        if( node != "Issuer" )
> +                            goto error;
> +                        this->s_issuer = s_value;
> +                        break;
> +                    case PKL_CREATOR:
> +                        if( node != "Creator" )
> +                            goto error;
> +                        this->s_creator = s_value;
> +                        break;
> +                    case PKL_ASSET_LIST:
> +                        /* impossible */
> +                        break;
> +                    case PKL_ANNOTATION_TEXT:
> +                        if( node != "AnnotationText" )
> +                            goto error;
> +                        this->s_annotation = s_value;
> +                        break;
> +                    case PKL_ICON_ID:
> +                        if( node != "IconId" )
> +                            goto error;
> +                        this->s_icon_id = s_value;
> +                        break;
> +                    case PKL_GROUP_ID:
> +                        if( node != "GroupId" )
> +                            goto error;
> +                        this->s_group_id = s_value;
> +                        break;
> +                    case PKL_SIGNER:
> +                    case PKL_SIGNATURE:
> +                        /* impossible */
> +                        break;
> +                    case ASSET_UNKNOWN:
> +                    default:
> +                        goto error;
> +                }
> +                break;
> +        }
> +    }
> +    /* TODO verify presence of mandatory fields*/
> +
> +    /* Close PKL XML*/
> +    this->CloseXml();
> +    return 0;
> +error:
> +    this->CloseXml();
> +    return -1;
> +}
> +
> +int PKL::FindCPLs()
> +{
> +    AssetList::iterator index = this->asset_list->begin();
> +    Asset *asset;
> +    CPL *cpl;
> +    cout << "Enter PKL::FindCPLs" << this->asset_list->size() <<endl;
> +    if ( this->vec_cpl.size() != 0 ) {
> +        msg_Err(this->p_demux, "CPLs already checked");
> +        return -1;
> +    }
> +
> +    while (index != this->asset_list->end()) {
for?
> +        asset = *index;
> +        if ( asset->getType().find("text/xml") == string::npos) {
> +            /* not an xml file */
> +            index++;
> +            continue;
> +        }
> +
> +        cpl = new CPL(this->p_demux,
> +                      this->s_dcp_path + asset->getPath(),
> +                      this->asset_list);
> +        cout << "IsCPL ? " << asset->getPath() <<  cpl->IsCPL()  <<endl;
> +        if ( cpl->IsCPL() )
> +            /* CPL Found */
> +            this->vec_cpl.push_back(cpl);
> +
> +        index++;
> +    }
> +    cout << "found " <<  this->vec_cpl.size() << " cpls" <<endl;
> +    return this->vec_cpl.size();
> +}
> +
> +
> +int PKL::ParseAssetList(string p_node, int p_type) {
> +    string node;
> +    int type;
> +
> +    cout << "PKL::ParseAssetList Enter = "<< p_node << endl;
> +    if (p_type != XML_READER_STARTELEM)
> +        goto error;
> +    if( p_node != "AssetList")
> +        goto error;
> +    while( ( type = ReadNextNode( this->p_xmlReader, node ) ) > 0 ) {
> +        cout << "PKL::ParseAssetList node = "<< node << endl;
> +        switch (type) {
> +            case XML_READER_STARTELEM:
> +                if( node =="Asset") {
> +                    if ( this->ParseAsset(node, type) )
> +                        goto error;
> +                } else
> +                    goto error;
> +                break;
> +            case XML_READER_TEXT:
> +                /* impossible */
impossible so useless
> +                break;
> +            case XML_READER_ENDELEM:
> +                if ( node == p_node) {
> +                    /* parse of chunklist finished */
> +                    goto end;
> +                }
> +                break;
> +            }
> +    }
> +end:
> +    return 0;
> +error:
> +    return -1;
> +}
> +
> +int PKL::ParseAsset(string p_node, int p_type) {
> +    string node;
> +    int type;
> +    string s_value;
> +    Asset *asset = NULL;
> +
> +    cout << "PKL::ParseAsset Enter = "<< p_node << endl;
> +    if (p_type != XML_READER_STARTELEM)
> +        goto error;
> +    if( p_node != "Asset")
> +        goto error;
> +
> +    /* 1st node shall be Id" */
> +    if (( type = ReadNextNode( this->p_xmlReader, node ) ) > 0)
> +        if ( ! ((type == XML_READER_STARTELEM) && (node == "Id")))
> +            goto error;
> +    if (( type = ReadNextNode( this->p_xmlReader, node ) ) > 0)
> +         if (type == XML_READER_TEXT) {
> +            s_value = node;
> +            if (unlikely(node.empty()))
> +                goto error;
> +            }
> +    if (( type = ReadNextNode( this->p_xmlReader, node ) ) > 0)
> +        if (type == XML_READER_ENDELEM) {
> +            asset = AssetMap::getAssetById(this->asset_list, s_value);
> +            cout << "Found asset with id=" << s_value << endl;
> +            if (asset  == NULL)
> +                goto error;
> +        }
> +     if ( asset->ParsePKL(this->p_xmlReader) )
> +        goto error;
> +    return 0;
> +error:
> +    return -1;
> +}
> +
> +int PKL::ParseSigner(string p_node, int p_type)
> +{
> +    string node;
> +    int type;
> +    bool b_stop_parse = false;
> +
> +    cout << "PKL::ParseSigner Enter = "<< p_node << endl;
> +    if (p_type != XML_READER_STARTELEM)
> +        goto error;
> +    if( p_node != "Signer")
> +        goto error;
> +
> +    while(  (! b_stop_parse) &&
why testing when you could just break or return?
> +            (( type = ReadNextNode( this->p_xmlReader, node ) ) > 0 ) ) {
> +        /* TODO not implemented. Just pase until end of Sihne node */
> +            if ((node == p_node) && (type = XML_READER_ENDELEM))
> +                b_stop_parse = true;
> +    }
> +
> +    if (b_stop_parse == false) {
> +        cout << "Parse of Signer finished bad" << endl;
> +        goto error;
> +    }
> +    return 0;
> +
> +error :
> +    return -1;
> +}
> +
> +int PKL::ParseSignature(string p_node, int p_type)
> +{
> +    string node;
> +    int type;
> +    bool b_stop_parse = false;
> +
> +    cout << "PKL::ParseSignature Enter = "<< p_node << endl;
> +    if (p_type != XML_READER_STARTELEM)
> +        goto error;
> +    if( p_node != "ds:Signature")
> +        goto error;
> +
> +    while(  (! b_stop_parse) &&
> +            (( type = ReadNextNode( this->p_xmlReader, node ) ) > 0 ) ) {
> +        /* TODO not implemented. Just pase until end of Sihne node */
> +            if ((node == p_node) && (type = XML_READER_ENDELEM))
> +                b_stop_parse = true;
> +    }
> +
> +    if (b_stop_parse == false) {
> +        cout << "Parse of Signature finished bad" << endl;
> +        goto error;
> +    }
> +    return 0;
> +
> +error :
> +    return -1;
> +}
> +
> +/*
> + * Reel Class
> + */
> +int Reel::Parse(string p_node, int p_type) {
> +    string node;
> +    int type;
> +    string s_value;
> +    bool b_stop_parse = false;
> +
> +    if (p_type != XML_READER_STARTELEM)
> +        goto error;
> +    if( p_node != "Reel")
> +        goto error;
> +
> +    while(  (! b_stop_parse) &&
> +            (( type = ReadNextNode(this->p_xmlReader, node ) ) > 0 ) ) {
> +        switch (type) {
> +            case XML_READER_STARTELEM:
> +                if (node =="Id") {
> +                    if ( ReadEndNode(this->p_xmlReader, node, type, s_value))
> +                        goto error;
> +                    this->s_id = s_value;
> +                } else if ( node =="AssetList" ) {
> +                    if (this->ParseAssetList(node, type))
> +                        goto error;
> +                } else {
> +                    /* unknown tag */
> +                    cout << "Reel::Parse, unknown tag: "<<node<<endl;
> +                    }
> +                break;
> +            case XML_READER_TEXT:
> +                /* impossible */
> +                goto error;
> +                break;
> +            case XML_READER_ENDELEM:
> +                /* verify correctness of end node */
> +                if ( node == p_node) {
> +                    /* TODO : verify id */
> +                    b_stop_parse = true;
> +                }
> +        }
> +    }
> +    return 0;
> +error:
> +    return -1;
> +}
> +
> +
> +Asset * Reel::getTrack(TrackType_t e_track)
> +{
> +Asset * p_asset =NULL;
> +
> +    switch (e_track) {
> +        case TRACK_PICTURE:
> +            p_asset = this->p_picture_track;
return this->p_picture_track;
> +            break;
> +        case TRACK_SOUND:
> +            p_asset = this->p_sound_track;
> +            break;
> +        case TRACK_SUBTITLE:
> +            p_asset = this->p_subtitle_track;
> +            break;
> +        case TRACK_UNKNOWN:
> +        default:
> +            break;
> +    }
> +    return p_asset;
> +}
> +
> +int Reel::ParseAssetList(string p_node, int p_type) {
> +    string node;
> +    int type;
> +    string s_value;
> +    bool b_stop_parse = false;
> +
> +    if (p_type != XML_READER_STARTELEM)
> +        goto error;
> +    if( p_node != "AssetList")
> +        goto error;
> +
> +    while(  (! b_stop_parse) &&
> +            (( type = ReadNextNode( this->p_xmlReader, node ) ) > 0 ) ) {
> +        switch (type) {
> +            case XML_READER_STARTELEM:
> +                if (node =="MainPicture") {
> +                    if ( this->ParseAsset(node, type, TRACK_PICTURE) )
> +                        goto error;
> +                } else if (node =="MainSound") {
> +                    if ( this->ParseAsset(node, type, TRACK_SOUND) )
> +                        goto error;
> +                } else if (node =="MainSubtitle") {
> +                    if ( this->ParseAsset(node, type, TRACK_SUBTITLE) )
> +                        goto error;
> +                } else {
> +                    /* unknown tag */
> +                    cout << "Reel::ParseAssetList, unknown tag: "<<node<<endl;
> +                    }
> +                break;
> +            case XML_READER_TEXT:
> +                /* impossible */
> +                goto error;
> +                break;
> +            case XML_READER_ENDELEM:
> +                /* verify correctness of end node */
> +                if ( node == p_node) {
> +                    /* TODO : verify id */
> +                    b_stop_parse = true;
> +                }
> +        }
> +    }
> +    return 0;
> +error:
> +    return -1;
> +}
> +
> +int Reel::ParseAsset(string p_node, int p_type, TrackType_t e_track) {
> +    string node;
> +    int type;
> +    string s_value;
> +    bool b_stop_parse = false;
> +    Asset *asset = NULL;
> +
> +    if (p_type != XML_READER_STARTELEM)
> +        goto error;
> +
> +    /* 1st node shall be Id */
> +    if (( type = ReadNextNode( this->p_xmlReader, node ) ) > 0)
> +        if ( ! ((type == XML_READER_STARTELEM) && (node == "Id")))
> +            goto error;
> +
> +    if ( ReadEndNode(this->p_xmlReader, node, type, s_value) )
> +        goto error;
> +
> +    asset = AssetMap::getAssetById(this->p_asset_list, s_value);
> +    cout << "Found asset with id=" << s_value << endl;
> +    if (asset  == NULL)
> +        goto error;
> +
> +    while(  (! b_stop_parse) &&
> +            (( type = ReadNextNode( this->p_xmlReader, node ) ) > 0 ) ) {
> +        switch (type) {
> +            case XML_READER_STARTELEM:
> +                if (node =="EditRate") {
> +                    if ( ReadEndNode(this->p_xmlReader, node, type, s_value))
> +                        goto error;
> +                } else if (node =="IntrinsicDuration") {
> +                    if ( ReadEndNode(this->p_xmlReader, node, type, s_value))
> +                        goto error;
> +                } else if (node =="EntryPoint") {
> +                    if ( ReadEndNode(this->p_xmlReader, node, type, s_value))
> +                        goto error;
> +                } else if (node =="Duration") {
> +                    if ( ReadEndNode(this->p_xmlReader, node, type, s_value))
> +                        goto error;
> +                } else if (node =="Duration") {
> +                    if ( ReadEndNode(this->p_xmlReader, node, type, s_value))
> +                        goto error;
> +                } else if (node =="KeyId") {
> +                    if ( ReadEndNode(this->p_xmlReader, node, type, s_value))
> +                        goto error;
> +                } else if (node =="Hash") {
> +                    if ( ReadEndNode(this->p_xmlReader, node, type, s_value))
> +                        goto error;
> +                } else if (node =="FrameRate") {
> +                    if ( ReadEndNode(this->p_xmlReader, node, type, s_value))
> +                        goto error;
> +                } else if (node =="ScreenAspectRatio") {
> +                    if ( ReadEndNode(this->p_xmlReader, node, type, s_value))
> +                        goto error;
> +                } else if (node =="Language") {
> +                    if ( ReadEndNode(this->p_xmlReader, node, type, s_value))
> +                        goto error;
same code used for different conditions, just extend your condition.
> +                } else {
> +                    /* unknown tag */
> +                    cout << "Reel::ParseAssetList, unknown tag: "<<node<<endl;
> +                    }
> +                break;
> +            case XML_READER_TEXT:
> +                /* impossible */
> +                goto error;
> +                break;
> +            case XML_READER_ENDELEM:
> +                /* verify correctness of end node */
> +                if ( node == p_node) {
> +                    /* TODO : verify id */
> +                    b_stop_parse = true;
> +                }
> +        }
> +    }
> +    /* store by track */
> +    switch (e_track) {
> +        case TRACK_PICTURE:
> +            this->p_picture_track = asset;
> +            break;
> +        case TRACK_SOUND:
> +            this->p_sound_track = asset;
> +            break;
> +        case TRACK_SUBTITLE:
> +            this->p_subtitle_track = asset;
> +            break;
> +        case TRACK_UNKNOWN:
> +        default:
> +            break;
> +    }
> +    return 0;
> +error:
> +    return -1;
> +}
> +
> +/*
> + * CPL Class
> + */
> +
> +CPL::CPL(demux_t * p_demux, string s_path, AssetList *_asset_list)
> +    : XmlFile(p_demux, s_path), asset_list( _asset_list)
> +{
> +    string node;
> +    int type;
> +
> +    if (this->OpenXml())
> +        return;
> +
> +    /* read 1st node  and verify that is a CPL */
> +    if ( (type = ReadNextNode(p_xmlReader, node)) > 0) {
> +        if ( (type == XML_READER_STARTELEM) && (node == "CompositionPlaylist") ) {
> +            this->type = XML_CPL;
> +        }
> +    }
> +    /* close xml */
> +    this->CloseXml();
> +};
> +
> +int CPL::Parse()
> +{
> +    string node;
> +    int type;
> +    string s_value;
> +    CPLTag_t i_tag = CPL_UNKNOWN;
> +    cout << "CPL::Parse Enter  "<< endl;
> +    if (this->OpenXml())
> +        return -1;
> +    /* read 1st node  and verify that is a CPL*/
> +    if ( (type = ReadNextNode(this->p_xmlReader, node)) > 0) {
> +        if ( ! ((type == XML_READER_STARTELEM) && (node == "CompositionPlaylist")) )    {
> +            msg_Err( this->p_demux, "Not a valid XML Composition Play List");
> +            goto error;
> +        }
> +    } else {
> +        msg_Err( this->p_demux, "XML read failed");
> +        goto error;
> +    }
> +    while( ( type = ReadNextNode( this->p_xmlReader, node ) ) > 0 ) {
> +        cout << "CPL::Parse node = "<< node << endl;
> +        switch (type) {
> +            case XML_READER_STARTELEM:
table?
> +                if( node =="Id")
> +                    i_tag = CPL_ID;
> +                else if( node == "AnnotationText")
> +                    i_tag = CPL_ANNOTATION_TEXT;
> +                else if( node == "IconId")
> +                    i_tag = CPL_ICON_ID;
> +                else if( node == "IssueDate")
> +                    i_tag = CPL_ISSUE_DATE;
> +                else if( node == "Issuer")
> +                    i_tag = CPL_ISSUER;
> +                else if( node == "Creator")
> +                    i_tag = CPL_CREATOR;
> +                else if( node == "ContentTitleText")
> +                    i_tag = CPL_CONTENT_TITLE;
> +                else if( node == "ContentKind")
> +                    i_tag = CPL_CONTENT_KIND;
> +                else if( node == "ContentVersion") {
> +                    i_tag = CPL_CONTENT_VERSION;
> +                    if ( this->DummyParse(node,type) )
> +                        goto error;
> +                    }
> +                else if( node == "RatingList") {
> +                    i_tag = CPL_RATING_LIST;
> +                    if ( this->DummyParse(node,type) )
> +                        goto error;
> +                    }
> +                else if( node == "ReelList") {
> +                    i_tag = CPL_REEL_LIST;
> +                    if ( this->ParseReelList(node, type) )
> +                        goto error;
> +                } else if( node == "Signer") {
> +                    i_tag = CPL_SIGNER;
> +                    if ( this->DummyParse(node, type) )
> +                        goto error;
> +                } else if( node == "ds:Signature") {
> +                    i_tag = CPL_SIGNATURE;
> +                    if ( this->DummyParse(node, type) )
> +                        goto error;
> +                } else {
> +                    i_tag = CPL_UNKNOWN;
> +                    goto error;
> +                }
> +                break;
> +           case XML_READER_TEXT:
> +                s_value = node;
> +                if (unlikely(node.empty()))
> +                    goto error;
> +                break;
> +
> +            case XML_READER_ENDELEM:
> +                switch (i_tag) {
> +                    case CPL_ID:
> +                        if( node != "Id" )
> +                            goto error;
> +                        this->s_id = s_value;
> +                        break;
> +                    case CPL_ANNOTATION_TEXT:
> +                        if( node != "AnnotationText" )
> +                            goto error;
> +                        this->s_annotation = s_value;
> +                        break;
> +                    case CPL_ICON_ID:
> +                        if( node != "IconId" )
> +                            goto error;
> +                        this->s_icon_id = s_value;
> +                        break;
> +                   case CPL_ISSUE_DATE:
> +                        if( node != "IssueDate" )
> +                            goto error;
> +                        this->s_issue_date= s_value;
> +                        break;
> +                    case CPL_ISSUER:
> +                        if( node != "Issuer" )
> +                            goto error;
> +                        this->s_issuer = s_value;
> +                        break;
> +                    case CPL_CREATOR:
> +                        if( node != "Creator" )
> +                            goto error;
> +                        this->s_creator = s_value;
> +                        break;
> +                    case CPL_CONTENT_TITLE:
> +                        if( node != "ContentTitleText" )
> +                            goto error;
> +                        this->s_content_title = s_value;
> +                        break;
> +                    case CPL_CONTENT_KIND:
> +                        if( node != "ContentKind" )
> +                            goto error;
> +                        this->s_content_kind = s_value;
> +                        break;
> +                    case CPL_CONTENT_VERSION:
> +                    case CPL_RATING_LIST:
> +                    case CPL_REEL_LIST:
> +                    case CPL_SIGNER:
> +                    case CPL_SIGNATURE:
> +                        /* impossible */
> +                        break;
> +                    case ASSET_UNKNOWN:
> +                    default:
> +                        goto error;
> +                }
> +                break;
> +        }
> +    }
> +    /* TODO verify presence of mandatory fields*/
> +
> +    /* Close Ckl XML*/
> +    this->CloseXml();
> +    return 0;
> +error:
> +    this->CloseXml();
> +    return -1;
> +}
> +
> +int CPL::ParseReelList(string p_node, int p_type) {
> +    string node;
> +    int type;
> +    Reel *p_reel;
> +    cout << "CPL::ParseReelList Enter = "<< p_node << endl;
> +    if (p_type != XML_READER_STARTELEM)
> +        return -1;
> +    if( p_node != "ReelList")
> +        return -1;
> +    while( ( type = ReadNextNode( this->p_xmlReader, node ) ) > 0 ) {
> +        cout << "CPL::ParseReelList node = "<< node << endl;
> +        switch (type) {
> +            case XML_READER_STARTELEM:
> +                p_reel = new Reel( this->asset_list, this->p_xmlReader );
check
> +                if( node =="Reel") {
> +                    if ( p_reel->Parse(node, type) )
> +                        goto error;
> +                } else
> +                    goto error;
> +                this->vec_reel.push_back(p_reel);
> +
> +                break;
> +            case XML_READER_TEXT:
> +                /* impossible */
> +                break;
> +            case XML_READER_ENDELEM:
> +                if ( node == p_node) {
> +                    goto end;
> +                }
> +                break;
> +            }
> +    }
> +end:
> +    return 0;
> +error:
> +    delete p_reel;
> +    return -1;
> +}
> +
> +
> +int CPL::DummyParse(string p_node, int p_type)
> +{
> +    string node;
> +    int type;
> +    bool b_stop_parse = false;
> +
> +    if (p_type != XML_READER_STARTELEM)
> +        return -1;
> +
> +    if (xml_ReaderIsEmptyElement( this->p_xmlReader))
> +        b_stop_parse = true;
> +
> +    while(  (! b_stop_parse) &&
> +            (( type = ReadNextNode( this->p_xmlReader, node ) ) > 0 ) ) {
> +        /* TODO not implemented. Just pase until end of input node */
> +        if ((node == p_node) && (type = XML_READER_ENDELEM))
> +            b_stop_parse = true;
> +    }
> +
> +    return 0;
> +}
> +
> +
> +#if 0
> +int main()
> +{
> +    AssetList _asset_list;
> +    AssetList::iterator itor;
> +    std::cout << "# creating Asset list :" << std::endl;
> +    Asset *_Asset1 = new Asset();
> +    _Asset1->setId("1234");
> +    _asset_list.push_back(_Asset1);
> +    Asset *_Asset2 = new Asset();
> +    _Asset2->setId("5678");
> +    _asset_list.push_back(_Asset2);
> +    cout << "Size of asset list = "<<_asset_list.size()<<endl;
> +    for (itor=_asset_list.begin(); itor != _asset_list.end() ; ++itor) {
> +        std::cout << "Id=" << (*itor)->getId() << std::endl;
> +    }
> +}
> +#endif
dead code
> diff --git a/modules/access/dcp/dcpparser.h b/modules/access/dcp/dcpparser.h
> new file mode 100644
> index 0000000..eadc0ad
> --- /dev/null
> +++ b/modules/access/dcp/dcpparser.h
> @@ -0,0 +1,297 @@
> +/*****************************************************************************
> + * Copyright (C) 2013 VLC authors and VideoLAN
> + *
> + * Authors: Nicolas Bertrand <nico at isf.cc>
> + *
> + * 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.
> + *****************************************************************************/
> +
> +/**
> + * @file dcpparser.h
> + * @brief Parse DCP XML files
> + */
> +
> +
> +#ifndef _DCPPARSER_H
> +#define _DCPPARSER_H
> +
> +#ifdef HAVE_CONFIG_H
> +#include "config.h"
> +#endif
> +
> +/* VLC core API headers */
> +#include <vlc_common.h>
> +#include <vlc_demux.h>
> +#include <vlc_plugin.h>
> +
> +#include <iostream>
> +#include <string>
> +#include <list>
> +#include <vector>
> +
> +using namespace std;
> +typedef enum {
> +    TRACK_UNKNOWN = 0,
> +    TRACK_PICTURE,
> +    TRACK_SOUND,
> +    TRACK_SUBTITLE
> +} TrackType_t;
> +
> +typedef enum {
> +    XML_UNKNOWN = 0,
> +    XML_ASSETMAP,
> +    XML_CPL,
> +    XML_PKL,
> +    XML_SUB,
> +} XmlType_t;
> +
> +class AssetList;
> +class PKL;
> +
> +/*! This struct stores the most important information about the DCP */
> +struct dcp_t
> +{
> +    string path;                    /*!< Path to DCP directory */
> +
> +    vector<PKL *> pkls;
> +    AssetList *p_asset_list;
> +
> +    string videofile;               /*!< Video file name */
> +    string audiofile;               /*!< Audio file name */
> +};
> +
> +
> +class XmlFile
> +{
> +public:
> +    XmlFile( demux_t * p_demux, string s_path);
> +
> +    virtual ~XmlFile( );
> +
> +    virtual int Parse() = 0;
> +
> +    bool IsCPL() { return type == XML_CPL; }
> +protected:
> +    demux_t      *p_demux;
> +    string       s_path;
> +    stream_t     *p_stream;
> +
> +    xml_t        *p_xml;
> +    xml_reader_t *p_xmlReader;
> +
> +    int OpenXml();
> +    void CloseXml();
> +
> +    XmlType_t type;
> +};
> +
> +class Chunk {
> +public:
> +    Chunk();
> +    int Parse(xml_reader_t *p_xmlReader, string p_node, int p_type);
> +    string getPath() { return this->s_path; };
> +private:
> +    string s_path;
> +    int i_vol_index;
> +    int i_offset;
> +    int i_length;
> +};
> +
> +class Asset {
> +public:
> +    /* Constructor */
> +    Asset ();
> +    virtual ~Asset() {};
> +
> +    void setId(string p_string ) { this->s_id = p_string; };
> +    void setPath(string p_string) { this->s_path = p_string; };
> +    void setPackingList(bool p_bool) { this->s_path = p_bool; };
> +    string getId() const { return this->s_id; } ;
> +    string getPath() const { return this->s_path; };
> +    string getType() const { return this->s_type; };
> +
> +    bool isPackingList() const { return this->b_is_packing_list; };
> +
> +    int Parse( xml_reader_t *p_xmlReader, string node, int type);
> +    int ParsePKL( xml_reader_t *p_xmlReader);
> +
> +    // TODO: remove
> +    void Dump();
> +
> +private:
> +    string      s_id;
> +    string      s_path;
> +    string      s_annotation;
> +    bool        b_is_packing_list;
> +    string      s_hash;
> +    uint32_t    ui_size;
> +    string      s_type;
> +    string      s_original_filename;
> +    TrackType_t e_track_type;
> +    string      s_edit_rate;
> +    int         i_intrisic_duration;
> +    int         i_entry_point;
> +    int         i_duration;
> +    /* encryption attribute */
> +    string      s_key_id;
> +    /* Picture attributes */
> +    string      s_frame_rate;
> +    string      s_screen_aspect_ratio;
> +    /* sound and subtitle */
> +    string      s_language;
> +
> +    demux_t     *p_demux;
> +    std::vector<Chunk> chunk_vec;
> +
> +
> +    int parseChunkList( xml_reader_t *p_xmlReader, string p_node, int p_type);
> +
> +};
> +
> +class AssetList: public std::list<Asset *> {};
> +
> +#if 0
> +class TrackFileAsset: public Asset
> +{
> +private:
> +    string s_key_id;
> +};
> +
> +class MarkerAsset: public Asset
> +{
> +
> +private:
> +    std:vector<string> vec_marker;
> +};
> +
> +class PictureTrackFileAsset: public TrackFileAsset
> +{
> +
> +private:
> +    string s_frame_rate;
> +    string s_screen_aspect_ratio;
> +};
> +
> +class SoundTrackFileAsset: public TrackFileAsset
> +{
> +
> +private:
> +    string s_language;
> +};
> +
> +class SubtitleTrackFileAsset: public TrackFileAsset
> +{
> +
> +private:
> +    string s_language;
> +};
> +#endif
> +
> +
> +class Reel
> +{
> +public:
> +    Reel(AssetList *asset_list, xml_reader_t *xmlReader)
> +        : p_asset_list(asset_list), p_xmlReader(xmlReader)
> +         {};
> +    int Parse(string p_node, int p_type);
> +    Asset * getTrack(TrackType_t e_track);
> +
> +private:
> +    AssetList *p_asset_list;
> +    xml_reader_t *p_xmlReader;
> +
> +    string s_id;
> +    string s_annotation;
> +    Asset  *p_picture_track;
> +    Asset  *p_sound_track;
> +    Asset  *p_subtitle_track;
> +    int ParseAssetList(string p_node, int p_type);
> +    int ParseAsset(string p_node, int p_type, TrackType_t e_track);
> +};
> +
> +class CPL : public XmlFile
> +{
> +public:
> +    CPL(demux_t *, string, AssetList*);
> +    virtual int Parse();
> +
> +    Reel *getReel(int pos) { return this->vec_reel[pos]; } ;
> +
> +private :
> +    AssetList *asset_list;
> +
> +    string s_id;
> +    string s_annotation;
> +    string s_icon_id;
> +    string s_issue_date;
> +    string s_issuer;
> +    string s_creator;
> +    string s_content_title;
> +    string s_content_kind;
> +    /* TODO:  ContentVersion, RatingList, signer and signature */
> +
> +    std::vector<Reel *>   vec_reel;
> +    int DummyParse(string p_node, int p_type);
> +    int ParseReelList(string p_node, int p_type);
> +};
> +
> +
> +class PKL : public XmlFile
> +{
> +public:
> +    PKL ( demux_t * p_demux, string s_path, AssetList *asset_list,
> +         string s_dcp_path);
> +    virtual int Parse();
> +
> +    int FindCPLs();
> +    CPL *getCPL(int pos) { return this->vec_cpl[pos]; };
> +
> +private:
> +    AssetList *asset_list;
> +
> +    string s_id;
> +    string s_annotation;
> +    string s_issue_date;
> +    string s_issuer;
> +    string s_creator;
> +    string s_icon_id;
> +    string s_group_id;
> +    string s_dcp_path;
> +    std::vector<CPL *> vec_cpl;
> +
> +    int ParseAssetList(string p_node, int p_type);
> +    int ParseAsset(string p_node, int p_type);
> +    int ParseSigner(string p_node, int p_type);
> +    int ParseSignature(string p_node, int p_type);
> +
> +};
> +
> +class AssetMap : public XmlFile {
> +
> +public:
> +    AssetMap( demux_t * p_demux, string s_path, dcp_t *_p_dcp)
> +        : XmlFile( p_demux, s_path ), p_dcp( _p_dcp) {};
> +
> +
> +    static Asset * getAssetById(AssetList*, const string p_id);
> +
> +    virtual int Parse();
> +private:
> +    dcp_t *p_dcp;
> +
> +    int ParseAssetList (xml_reader_t *p_xmlReader, string p_node, int p_type);
> +};
> +#endif /* _DCPPARSER_H */
> -- 
> 1.7.9.5

Regards,

-- 
Denis Charmet - TypX
Le mauvais esprit est un art de vivre



More information about the vlc-devel mailing list