[vlc-devel] [PATCH V2] dcp: Creation of access-demux module for DCP (using asdcplib)

Rémi Denis-Courmont remi at remlab.net
Sat Jul 20 15:35:05 CEST 2013


s/Creation of //

Le jeudi 18 juillet 2013 14:07:53 Nicolas Bertrand a écrit :
> From: Simona-Marinela Prodea <simonamarinela.prodea at etu.enseeiht.fr>
> 
> ---
>  configure.ac              |   17 +
>  modules/access/Modules.am |    7 +
>  modules/access/dcp.cpp    | 1198
> +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 1222
> insertions(+)
>  create mode 100644 modules/access/dcp.cpp
> 
> diff --git a/configure.ac b/configure.ac
> index e50ae14..e209bbb 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -1962,6 +1962,23 @@ fi
>  AM_CONDITIONAL(HAVE_AVFOUNDATION, [test "${have_avfoundation}" != "no"])
> 
>  dnl
> +dnl  DCP plugin (using asdcplib)
> +dnl
> +AC_ARG_ENABLE(dcp,
> +  AS_HELP_STRING([--enable-dcp],[Digital Cinema Package support using
> asdcplib (default auto)]))
> +have_asdcp="no"
> +AS_IF([test "${enable_dcp}" != "no"], [
> +  AC_LANG_PUSH(C++)
> +  AC_CHECK_HEADERS( [[AS@&t at _DCP.h]],
> +    [have_asdcp="yes"],
> +    [AS_IF( [test "${enable_dcp}" = "yes"],

Does this work on all shells if enable_dcp is not set? I think we usually 
prefix with x for that kind of test.

> +      [AC_MSG_ERROR( [ ASDCP library cannot be found (needed for dcp
> module). Either use --enable-dcp=no or install asdcp library:
> http://www-dev.pub.cinecert.com/asdcplib/download/ ] )])
> +     ])
> +  AC_LANG_POP(C++)
> +])
> +AM_CONDITIONAL(HAVE_ASDCP, [test "${have_asdcp}" != "no"])
> +
> +dnl
>  dnl  Demux plugins
>  dnl
> 
> diff --git a/modules/access/dcp.cpp b/modules/access/dcp.cpp
> new file mode 100644
> index 0000000..3c4fbaf
> --- /dev/null
> +++ b/modules/access/dcp.cpp
> @@ -0,0 +1,1198 @@
> +/**************************************************************************
> *** + * Copyright (C) 2012-2013 VLC authors and VideoLAN
> + *
> + * Authors:
> + *          Claire Etienne
> + *          Aurélie Sbinné
> + *          Pierre Villard <pierre dot villard dot fr at gmail dot com>
> + *          Samuel Kerjose
> + *          Julien Puyobro
> + *          Simona-Marinela Prodea <simona dot marinela dot prodea at gmail
> dot com> + *
> + * 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
> + * @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>
> +
> +/* ASDCP headers */
> +#include <AS_DCP.h>
> +
> +using namespace ASDCP;
> +using namespace std;
> +
> +#define FRAME_BUFFER_SIZE 1302083 /* maximum frame length, in bytes, after
> +                                     "Digital Cinema System Specification
> Version 1.2 +                                     with Errata as of 30
> August 2012" */ +
> +/* Forward declarations */
> +static int Open( vlc_object_t * );
> +static void Close( vlc_object_t * );
> +
> +/* Module descriptor */
> +vlc_module_begin()
> +    set_shortname( N_( "DCP" ) )
> +    add_shortcut( "dcp" )
> +    set_description( N_( "Digital Cinema Package access-demux module" ) )
> +    set_capability( "access_demux", 0 )
> +    set_category( CAT_INPUT )
> +    set_subcategory( SUBCAT_INPUT_ACCESS )
> +    set_callbacks( Open, Close )
> +vlc_module_end()
> +
> +//! File structure class
> +class file_t
> +{
> + public:
> +    string id;
> +    string path;
> +};

struct?

> +
> +//! DCP class
> +/*! This class stores the most important information about the DCP */
> +class dcp_t
> +{
> + public:
> +    string path;             /*!< Path to DCP directory */
> +    char * assetmapURI;      /*!< ASSETMAP XML file URI  - will be
> allocated with malloc in vlc_path2uri */ +    char * cplfileURI;       /*!<
> CPL XML file URI - will be allocated with malloc in vlc_path2uri */ +   
> string pklfile;          /*!< PKL XML file name */
> +    string videofile;        /*!< Video file name */
> +    string audiofile;        /*!< Audio file name */
> +    int nb_files;            /*!< Number of files defined in ASSETMAP */
> +    file_t *files[20];       /*!< Files defined in ASSETMAP : we assume
> that there are less than 20 files */ +
> +    dcp_t():
> +        assetmapURI( NULL ),
> +        cplfileURI( NULL ),
> +        nb_files( 0 )
> +    {
> +        for( int i=0; i < 20; i++ )
> +            files[i] = NULL;
> +    }
> +    ~dcp_t()
> +    {
> +        free( assetmapURI );
> +        free( cplfileURI );
> +        for( int i=0; i < 20; i++ )
> +            delete files[i];
> +    }
> +};

Class with everything public is really odd...

> +
> +/* ASDCP library (version 1.10.48) can handle files having one of the
> following Essence Types, as defined in AS_DCP.h: +    ESS_UNKNOWN,     //
> the file is not a supported AS-DCP essence container +    ESS_MPEG2_VES,  
> // the file contains an MPEG video elementary stream +    ESS_JPEG_2000,  
> // the file contains one or more JPEG 2000 codestreams +   
> ESS_PCM_24b_48k, // the file contains one or more PCM audio pairs +   
> ESS_PCM_24b_96k, // the file contains one or more PCM audio pairs +   
> ESS_TIMED_TEXT,  // the file contains an XML timed text document and one or
> more resources +    ESS_JPEG_2000_S, // the file contains one or more JPEG
> 2000 codestream pairs (stereoscopic). +
> +    The classes for handling these essence types are defined in AS_DCP.h
> and are different for each essence type, respectively. The demux_sys_t
> structure contains members for handling each of these essence types. +*/
> +
> +class demux_sys_t
> +{
> + public:
> +    /* ASDCP Picture Essence Type */
> +    EssenceType_t PictureEssType;
> +
> +    /* ASDCP Video MXF Reader */
> +    union
> +    {
> +        /* JPEG2000 essence type */
> +        JP2K::MXFReader *p_PicMXFReader;
> +
> +        /* JPEG2000 stereoscopic essence type */
> +        JP2K::MXFSReader *p_PicMXFSReader;
> +
> +        /* MPEG2 essence type */
> +        MPEG2::MXFReader *p_VideoMXFReader;
> +    };
> +
> +    /* ASDCP Picture Descriptor */
> +    union
> +    {
> +        /* JPEG2000 and JPEG2000 stereoscopic essence types */
> +        JP2K::PictureDescriptor *p_PicDesc;
> +
> +        /* MPEG2 essence type */
> +        MPEG2::VideoDescriptor *p_VideoDesc;
> +    };
> +
> +    /* ASDCP Audio MXF Reader */
> +    PCM::MXFReader *p_AudioMXFReader;
> +
> +    /* ASDCP Audio Descriptor */
> +    PCM::AudioDescriptor *p_AudioDesc;
> +
> +    /* elementary streams */
> +    es_out_t *p_out;
> +    es_out_id_t *p_video_es;
> +    es_out_id_t *p_audio_es;
> +
> +    /* DCP object */
> +    dcp_t *p_dcp;
> +
> +    /* current frame number */
> +    uint32_t frame_no;
> +
> +    /* frame rate */
> +    unsigned int frame_rate_num;
> +    unsigned int frame_rate_denom;
> +
> +    /* total number of frames */
> +    uint32_t frames_total;
> +
> +    demux_sys_t():
> +        p_PicMXFReader( NULL ),
> +        p_PicDesc( NULL ),
> +        p_AudioMXFReader( NULL ),
> +        p_AudioDesc( NULL ),
> +        p_out( NULL ),
> +        p_video_es( NULL ),
> +        p_audio_es( NULL ),
> +        p_dcp( NULL )
> +    {
> +        PictureEssType = ESS_UNKNOWN;
> +    }
> +    ~demux_sys_t()
> +    {
> +        switch ( PictureEssType )
> +        {
> +            case ESS_UNKNOWN:
> +                break;
> +            case ESS_JPEG_2000:
> +                delete p_PicMXFReader;
> +                delete p_PicDesc;
> +                break;
> +            case ESS_JPEG_2000_S:
> +                delete p_PicMXFSReader;
> +                delete p_PicDesc;
> +                break;
> +            case ESS_MPEG2_VES:
> +                delete p_VideoMXFReader;
> +                delete p_VideoDesc;
> +                break;
> +            default:
> +                break;
> +        }
> +        delete p_AudioMXFReader;
> +        delete p_AudioDesc;
> +        if( p_video_es )
> +            es_out_Del( p_out, p_video_es );
> +        if( p_audio_es )
> +            es_out_Del( p_out, p_audio_es );

AFAIR, you do not need to delete ES explicitly, unless you want to add/remove 
while playing.

> +        delete p_dcp;
> +    }
> +};
> +
> +/**************************************************************************
> *** + * Local prototypes
> +
> ***************************************************************************
> **/ +
> +static int Demux( demux_t * );
> +static int Control( demux_t *, int, va_list );
> +
> +int dcpInit ( demux_t *p_demux );
> +int parserXML ( demux_t * p_demux );
> +void fillVideoFmt( video_format_t * fmt, unsigned int width, unsigned int
> height, unsigned int frame_rate_num, unsigned int frame_rate_denom ); +void
> freeMem( demux_t *p_demux );
> +
> +
> +
> +/**************************************************************************
> *** + * Open: module init function
> +
> ***************************************************************************
> **/ +static int Open( vlc_object_t *obj )
> +{
> +    demux_t *p_demux = ( demux_t* ) obj;
> +    demux_sys_t *p_sys = NULL;

Assigned value is never used.

> +    es_format_t video_format, audio_format;
> +    vlc_fourcc_t fcc;
> +    int retval;
> +
> +    if( !p_demux->psz_file )
> +        return VLC_EGENERIC;
> +
> +    /* handle the DCP directory, saving the paths for audio and video file,
> returning error if unsuccessful */ +    if( ( retval = dcpInit( p_demux ) )
> )
> +    {
> +        freeMem( p_demux );
> +        return retval;

goto is NOT considered harmful.

> +    }
> +
> +    p_sys = p_demux->p_sys;
> +
> +    /***************************************************
> +     ***************** open video file *****************
> +     ***************************************************/
> +    EssenceType( p_sys->p_dcp->videofile.c_str(), p_sys->PictureEssType );
> +
> +    switch( p_sys->PictureEssType )
> +    {
> +        case ESS_UNKNOWN:
> +            msg_Err( p_demux, "The file %s is not a supported AS_DCP
> essence container", p_sys->p_dcp->videofile.c_str() ); +           
> freeMem( p_demux );
> +            return VLC_EGENERIC;
> +        case ESS_JPEG_2000:
> +        {
> +            fcc = VLC_CODEC_JPEG2000;
> +            JP2K::MXFReader *p_PicMXFReader = p_sys->p_PicMXFReader = new (
> nothrow ) JP2K::MXFReader(); +            JP2K::PictureDescriptor
> *p_PicDesc = p_sys->p_PicDesc = new ( nothrow ) JP2K::PictureDescriptor();
> +
> +            if( !p_PicMXFReader || !p_PicDesc )
> +            {
> +                msg_Err( p_demux, "Could not alloc object for handling MXF"
> ); +                freeMem( p_demux );
> +                return VLC_ENOMEM;
> +            }
> +            Result_t result = p_PicMXFReader->OpenRead(
> p_sys->p_dcp->videofile.c_str() ); +            if( !ASDCP_SUCCESS( result
> ) )
> +            {
> +                msg_Err( p_demux, "File %s could not be opened with ASDCP",
> p_sys->p_dcp->videofile.c_str() ); +                freeMem( p_demux );
> +                return VLC_EGENERIC;
> +            }
> +
> +            p_PicMXFReader->FillPictureDescriptor( *p_PicDesc );
> +
> +            es_format_Init( &video_format, VIDEO_ES, fcc );
> +            fillVideoFmt( &video_format.video, p_PicDesc->StoredWidth,
> p_PicDesc->StoredHeight, p_PicDesc->EditRate.Numerator,
> p_PicDesc->EditRate.Denominator ); +
> +            p_sys->p_PicMXFReader = p_PicMXFReader;
> +            p_sys->p_PicDesc = p_PicDesc;
> +            p_sys->frame_no = 0;
> +            p_sys->frame_rate_num = p_PicDesc->EditRate.Numerator;
> +            p_sys->frame_rate_denom = p_PicDesc->EditRate.Denominator;
> +            p_sys->frames_total = p_PicDesc->ContainerDuration;
> +
> +            break;
> +        }
> +        case ESS_JPEG_2000_S:
> +        {
> +            fcc = VLC_CODEC_JPEG2000;
> +            JP2K::MXFSReader *p_PicMXFSReader = p_sys->p_PicMXFSReader =
> new ( nothrow ) JP2K::MXFSReader(); +            JP2K::PictureDescriptor
> *p_PicDesc = p_sys->p_PicDesc = new ( nothrow ) JP2K::PictureDescriptor();
> +
> +            if( !p_PicMXFSReader || !p_PicDesc )
> +            {
> +                msg_Err( p_demux, "Could not alloc object for handling MXF"
> ); +                freeMem( p_demux );
> +                return VLC_ENOMEM;
> +            }
> +
> +            Result_t result = p_PicMXFSReader->OpenRead(
> p_sys->p_dcp->videofile.c_str() ); +            if( !ASDCP_SUCCESS( result
> ) )
> +            {
> +                msg_Err( p_demux, "File %s could not be opened with ASDCP",
> p_sys->p_dcp->videofile.c_str() ); +                freeMem( p_demux );
> +                return VLC_EGENERIC;
> +            }
> +
> +            p_PicMXFSReader->FillPictureDescriptor( *p_PicDesc );
> +
> +            es_format_Init( &video_format, VIDEO_ES, fcc );
> +            fillVideoFmt( &video_format.video, p_PicDesc->StoredWidth,
> p_PicDesc->StoredHeight, p_PicDesc->EditRate.Numerator,
> p_PicDesc->EditRate.Denominator ); +
> +            p_sys->p_PicMXFSReader = p_PicMXFSReader;
> +            p_sys->p_PicDesc = p_PicDesc;
> +            p_sys->frame_no = 0;
> +            p_sys->frame_rate_num = p_PicDesc->EditRate.Numerator;
> +            p_sys->frame_rate_denom = p_PicDesc->EditRate.Denominator;
> +            p_sys->frames_total = p_PicDesc->ContainerDuration;
> +
> +            break;
> +        }
> +        case ESS_MPEG2_VES:
> +        {
> +            fcc = VLC_CODEC_MPGV;
> +            MPEG2::MXFReader *p_VideoMXFReader = p_sys->p_VideoMXFReader =
> new ( nothrow ) MPEG2::MXFReader(); +            MPEG2::VideoDescriptor
> *p_VideoDesc = p_sys->p_VideoDesc = new ( nothrow )
> MPEG2::VideoDescriptor(); +
> +            if( !p_VideoMXFReader || !p_VideoDesc )
> +            {
> +                msg_Err( p_demux, "Could not alloc object for handling MXF"
> ); +                freeMem( p_demux );
> +                return VLC_ENOMEM;
> +            }
> +
> +            Result_t result = p_VideoMXFReader->OpenRead(
> p_sys->p_dcp->videofile.c_str() ); +            if( !ASDCP_SUCCESS( result
> ) )
> +            {
> +                msg_Err( p_demux, "File %s could not be opened with ASDCP",
> p_sys->p_dcp->videofile.c_str() ); +                freeMem( p_demux );
> +                return VLC_EGENERIC;
> +            }
> +
> +            p_VideoMXFReader->FillVideoDescriptor( *p_VideoDesc );
> +
> +            es_format_Init( &video_format, VIDEO_ES, fcc );
> +            fillVideoFmt( &video_format.video, p_VideoDesc->StoredWidth,
> p_VideoDesc->StoredHeight, p_VideoDesc->EditRate.Numerator,
> p_VideoDesc->EditRate.Denominator ); +
> +            p_sys->p_VideoMXFReader = p_VideoMXFReader;
> +            p_sys->p_VideoDesc = p_VideoDesc;
> +            p_sys->frame_no = 0;
> +            p_sys->frame_rate_num = p_VideoDesc->EditRate.Numerator;
> +            p_sys->frame_rate_denom = p_VideoDesc->EditRate.Denominator;
> +            p_sys->frames_total = p_VideoDesc->ContainerDuration;
> +
> +            break;
> +        }
> +        default:
> +            msg_Err( p_demux, "Unrecognized video format" );
> +            freeMem( p_demux );
> +            return VLC_EGENERIC;
> +    }
> +
> +    if( ( p_sys->p_video_es = es_out_Add( p_demux->out, &video_format ) )
> == NULL ) +    {
> +        msg_Err( p_demux, "Failed to add video es" );
> +        freeMem( p_demux );
> +        return VLC_EGENERIC;
> +    }
> +
> +    /***************************************************
> +     ***************** open audio file *****************
> +     ***************************************************/
> +    EssenceType_t AudioEssType;
> +    EssenceType( p_sys->p_dcp->audiofile.c_str(), AudioEssType );
> +    switch( AudioEssType )
> +    {
> +        case ESS_UNKNOWN:
> +            msg_Err( p_demux, "The file %s is not a supported AS_DCP
> essence container", p_sys->p_dcp->audiofile.c_str() ); +           
> freeMem( p_demux );
> +            return VLC_EGENERIC;
> +        case ESS_PCM_24b_48k:
> +        case ESS_PCM_24b_96k:
> +            fcc = VLC_CODEC_S24L;
> +            break;
> +        default:
> +            msg_Err( p_demux, "Unrecognized audio format" );
> +            freeMem( p_demux );
> +            return VLC_EGENERIC;
> +    }
> +
> +    PCM::MXFReader *p_AudioMXFReader = p_sys->p_AudioMXFReader = new (
> nothrow ) PCM::MXFReader(); +    PCM::AudioDescriptor *p_AudioDesc =
> p_sys->p_AudioDesc = new ( nothrow ) PCM::AudioDescriptor(); +
> +    if( !p_AudioMXFReader || !p_AudioDesc )
> +    {
> +        msg_Err( p_demux, "Could not alloc object for handling MXF" );
> +        freeMem( p_demux );
> +        return VLC_ENOMEM;
> +    }
> +
> +    Result_t result = p_AudioMXFReader->OpenRead(
> p_sys->p_dcp->audiofile.c_str() ); +    if( !ASDCP_SUCCESS( result ) )
> +    {
> +        msg_Err( p_demux, "File %s could not be opened with ASDCP",
> p_sys->p_dcp->audiofile.c_str() ); +        freeMem( p_demux );
> +        return VLC_EGENERIC;
> +    }
> +
> +    p_AudioMXFReader->FillAudioDescriptor( *p_AudioDesc );
> +
> +    es_format_Init( &audio_format, AUDIO_ES, fcc );
> +    if( p_AudioDesc->AudioSamplingRate.Denominator != 0 )
> +        audio_format.audio.i_rate =
> p_AudioDesc->AudioSamplingRate.Numerator /
> p_AudioDesc->AudioSamplingRate.Denominator; +   
> audio_format.audio.i_bitspersample = p_AudioDesc->QuantizationBits; +   
> audio_format.audio.i_blockalign = p_AudioDesc->BlockAlign;
> +    audio_format.audio.i_channels = p_AudioDesc->ChannelCount;
> +
> +    p_sys->p_AudioMXFReader = p_AudioMXFReader;
> +    p_sys->p_AudioDesc = p_AudioDesc;
> +
> +
> +    if( ( p_sys->p_audio_es = es_out_Add( p_demux->out, &audio_format ) )
> == NULL ) +    {
> +        msg_Err( p_demux, "Failed to add audio es" );
> +        freeMem( p_demux );
> +        return VLC_EGENERIC;
> +    }
> +
> +    p_sys->p_out = p_demux->out;
> +    p_demux->pf_demux = Demux;
> +    p_demux->pf_control = Control;
> +    p_demux->p_sys = p_sys;
> +
> +    return VLC_SUCCESS;
> +}
> +
> +
> +/**************************************************************************
> *** + * Close: module destroy function
> +
> ***************************************************************************
> **/ +static void Close( vlc_object_t *obj )
> +{
> +    demux_t *p_demux = ( demux_t* ) obj;
> +    freeMem( p_demux );

I would inline that function.

> +}
> +
> +
> +
> +/**************************************************************************
> *** + * Demux: DCP Demuxing function
> +
> ***************************************************************************
> **/ +static int Demux( demux_t *p_demux )
> +{
> +    demux_sys_t *p_sys = p_demux->p_sys;
> +    block_t *p_video_frame = NULL, *p_audio_frame = NULL;
> +    uint32_t i = p_sys->frame_no;
> +    mtime_t pts = 0;
> +
> +    if( i == p_sys->frames_total )
> +        return VLC_SUCCESS;

AFAIR, Demux() must return 0 (EOS), -1 (error) or 1 (OK), not VLC_* codes.

> +
> +    /* video frame */
> +    switch( p_sys->PictureEssType )
> +    {
> +        case ESS_JPEG_2000:
> +        {
> +            JP2K::MXFReader *p_PicMXFReader = p_sys->p_PicMXFReader;
> +            JP2K::FrameBuffer PicFrameBuff( FRAME_BUFFER_SIZE );
> +
> +            Result_t result = p_PicMXFReader->ReadFrame( i, PicFrameBuff,
> 0, 0 ); +            if( ! ASDCP_SUCCESS( result ) )
> +            {
> +                msg_Err( p_demux, "Couldn't read frame with ASDCP");
> +                return VLC_EGENERIC;
> +            }
> +
> +            if( ( p_video_frame = block_Alloc( PicFrameBuff.Size() ) ) !=
> NULL ) +                memcpy( p_video_frame->p_buffer,
> PicFrameBuff.Data(), PicFrameBuff.Size() );

You should probably try to avoid memory copy here...

> +            else
> +            {
> +                msg_Err( p_demux, "Couldn't alloc block for elementary
> stream" );

We do not usually print error messages on memory allocation failure, unless it 
is really likely (meaning the allocation is large). This clutters the code, 
and won't work anyway as memory needs to be allocated to log errors.

> +                return VLC_ENOMEM;
> +            }
> +
> +            p_video_frame->i_buffer = PicFrameBuff.Size();
> +            break;
> +        }
> +        case ESS_JPEG_2000_S:
> +        {
> +            JP2K::MXFSReader *p_PicMXFReader = p_sys->p_PicMXFSReader;
> +            JP2K::FrameBuffer PicFrameBuff( FRAME_BUFFER_SIZE );
> +
> +            Result_t result = p_PicMXFReader->ReadFrame( i, JP2K::SP_LEFT,
> PicFrameBuff, 0, 0 ); +            if( ! ASDCP_SUCCESS( result ) )
> +            {
> +                msg_Err( p_demux, "Couldn't read frame with ASDCP");
> +                return VLC_EGENERIC;
> +            }
> +
> +            if( ( p_video_frame = block_Alloc( PicFrameBuff.Size() ) ) !=
> NULL ) +                memcpy( p_video_frame->p_buffer,
> PicFrameBuff.Data(), PicFrameBuff.Size() ); +            else
> +            {
> +                msg_Err( p_demux, "Couldn't alloc block for elementary
> stream" ); +                return VLC_ENOMEM;
> +            }
> +
> +            p_video_frame->i_buffer = PicFrameBuff.Size();
> +            break;
> +        }
> +        case ESS_MPEG2_VES:
> +        {
> +            MPEG2::MXFReader *p_VideoMXFReader = p_sys->p_VideoMXFReader;
> +            MPEG2::FrameBuffer VideoFrameBuff( FRAME_BUFFER_SIZE );
> +
> +            Result_t result = p_VideoMXFReader->ReadFrame( i,
> VideoFrameBuff, 0, 0 ); +            if( ! ASDCP_SUCCESS( result ) )
> +            {
> +                msg_Err( p_demux, "Couldn't read frame with ASDCP");
> +                return VLC_EGENERIC;
> +            }
> +
> +            if( ( p_video_frame = block_Alloc( VideoFrameBuff.Size() ) ) !=
> NULL ) +                memcpy( p_video_frame->p_buffer,
> VideoFrameBuff.Data(), VideoFrameBuff.Size() ); +            else
> +            {
> +                msg_Err( p_demux, "Couldn't alloc block for elementary
> stream" ); +                return VLC_ENOMEM;
> +            }
> +
> +            p_video_frame->i_buffer = VideoFrameBuff.Size();
> +            break;
> +        }
> +        default:
> +            msg_Err( p_demux, "Unrecognized video format" );
> +            return VLC_EGENERIC;
> +    }
> +
> +    if( p_sys->frame_rate_num != 0 )
> +    {
> +        p_video_frame->i_length = 1000000 * p_sys->frame_rate_denom /
> p_sys->frame_rate_num; +        p_video_frame->i_pts = 1000000 *
> p_sys->frame_no * p_sys->frame_rate_denom / p_sys->frame_rate_num; +    }
> +    else
> +    {
> +        msg_Err( p_demux, "Frame rate 0");
> +        return VLC_EBADVAR;

Why that error?


> +    }
> +
> +    /* audio frame */
> +    PCM::MXFReader *p_AudioMXFReader = p_sys->p_AudioMXFReader;
> +    PCM::FrameBuffer AudioFrameBuff( PCM::CalcFrameBufferSize(
> *p_sys->p_AudioDesc ) ); +
> +    Result_t result = p_AudioMXFReader->ReadFrame( i, AudioFrameBuff, 0, 0
> ); +    if( ! ASDCP_SUCCESS( result ) )
> +    {
> +        msg_Err( p_demux, "Couldn't read frame with ASDCP");
> +        return VLC_EGENERIC;
> +    }
> +
> +    if( ( p_audio_frame = block_Alloc( AudioFrameBuff.Size() ) ) != NULL )
> +        memcpy( p_audio_frame->p_buffer, AudioFrameBuff.Data(),
> AudioFrameBuff.Size() ); +    else
> +    {
> +        msg_Err( p_demux, "Couldn't alloc block for elementary stream" );
> +        return VLC_ENOMEM;
> +    }
> +
> +    p_audio_frame->i_buffer = AudioFrameBuff.Size();
> +    if( p_sys->frame_rate_num != 0 )
> +    {
> +        p_audio_frame->i_length = 1000000 * p_sys->frame_rate_denom /
> p_sys->frame_rate_num; +        p_audio_frame->i_pts = 1000000 *
> p_sys->frame_no * p_sys->frame_rate_denom / p_sys->frame_rate_num; +    }
> +    else
> +    {
> +        msg_Err( p_demux, "Frame rate 0");
> +        return VLC_EBADVAR;

Same here.

> +    }
> +
> +    if( p_video_frame->i_pts < p_audio_frame->i_pts )
> +        pts = p_video_frame->i_pts;
> +    else
> +        pts = p_audio_frame->i_pts;
> +    es_out_Control( p_demux->out, ES_OUT_SET_PCR, pts );
> +    es_out_Send( p_demux->out, p_sys->p_video_es, p_video_frame );
> +    es_out_Send( p_demux->out, p_sys->p_audio_es, p_audio_frame );
> +
> +    p_sys->frame_no++;
> +
> +    return 1;
> +}
> +
> +/**************************************************************************
> *** + * Control: handle the controls
> +
> ***************************************************************************
> **/ +static int Control( demux_t *p_demux, int query, va_list args )
> +{
> +    double f,*pf;
> +    bool *pb;
> +    int64_t *pi64, i64;
> +    demux_sys_t *p_sys = p_demux->p_sys;
> +
> +    switch ( query )
> +    {
> +        case DEMUX_CAN_PAUSE:
> +        case DEMUX_CAN_CONTROL_PACE:
> +            pb = ( bool* ) va_arg ( args, bool* );
> +            *pb = true;
> +            return VLC_SUCCESS;

break

> +        case DEMUX_SET_PAUSE_STATE:
> +            return VLC_SUCCESS;
> +        case DEMUX_CAN_SEEK:
> +            if( p_sys->PictureEssType != ESS_MPEG2_VES )
> +            {
> +                pb = (bool *)va_arg( args, bool * );
> +                *pb = true;
> +                return VLC_SUCCESS;
> +            }
> +            else
> +            {
> +                msg_Warn( p_demux, "Unknown query %d in DCP Control", query
> ); +                return VLC_EGENERIC;

This is not allowed to fail.

> +            }
> +        case DEMUX_GET_POSITION:
> +            pf = ( double* ) va_arg ( args, double* ); *pf = 0.0;
> +            if( p_sys->frames_total != 0 )
> +                *pf = (double) p_sys->frame_no / (double)
> p_sys->frames_total; +            else
> +            {
> +                msg_Err( p_demux, "Total number of frames is 0" );
> +                break;
> +            }
> +            return VLC_SUCCESS;
> +        case DEMUX_SET_POSITION:
> +            f = ( double ) va_arg ( args, double );
> +            p_sys->frame_no = (int) ( f * p_sys->frames_total );
> +            return VLC_SUCCESS;

break again and ditto further

> +        case DEMUX_GET_LENGTH:
> +            pi64 = ( int64_t* ) va_arg ( args, int64_t* );
> +            if( p_sys->frame_rate_num != 0 )
> +                *pi64 = (int) ( ( p_sys->frames_total *
> p_sys->frame_rate_denom / p_sys->frame_rate_num ) * 1000000 ); +           
> else
> +            {
> +                msg_Err( p_demux, "Frame rate is 0" );
> +                return VLC_EBADVAR;

Return 0 length if unknown.

> +            }
> +            return VLC_SUCCESS;
> +        case DEMUX_GET_TIME:
> +            pi64 = ( int64_t* ) va_arg ( args, int64_t* );
> +            if( p_sys->frame_rate_num != 0 )
> +                *pi64 = (int) ( ( p_sys->frame_no *p_sys->frame_rate_denom
> / p_sys->frame_rate_num ) * 1000000 ); +            else
> +            {
> +                msg_Err( p_demux, "Frame rate is 0" );
> +                return VLC_EBADVAR;
> +            }

You don't need the frame rate to compute the current time

> +            return VLC_SUCCESS;
> +        case DEMUX_SET_TIME:
> +            i64 = ( int64_t ) va_arg ( args, int64_t );
> +            if( p_sys->frame_rate_num != 0 )
> +            {
> +                p_sys->frame_no = i64 * p_sys->frame_rate_num / ( 1000000 *
> p_sys->frame_rate_denom ); +                es_out_Control( p_demux->out,
> ES_OUT_SET_NEXT_DISPLAY_TIME, ( mtime_t ) i64 ); +            }
> +            else
> +            {
> +                msg_Err( p_demux, "Frame rate is 0" );
> +                return VLC_EBADVAR;
> +            }
> +            return VLC_SUCCESS;
> +        default:
> +            msg_Warn( p_demux, "Unknown query %d in DCP Control", query );
> +            return VLC_EGENERIC;
> +    }
> +
> +    return VLC_SUCCESS;
> +}
> +
> +
> +/**************************************************************************
> *** + * Low-level functions : string manipulation, free function, etc
> +
> ***************************************************************************
> **/ +/**
> + * Function to check if a file name ends with a given suffix
> + * @param str File name
> + * @param suffix Suffix to look for
> + * @return true if the file name ends with the given suffix, false
> otherwise + */
> +bool endsWith( const char * str, const char * suffix )
> +{
> +    if( !str || !suffix )
> +        return false;
> +    size_t lenstr = strlen( str );
> +    size_t lensuffix = strlen( suffix );
> +    if( lensuffix >  lenstr )
> +        return false;
> +    if( strncasecmp( str + lenstr - lensuffix, suffix, lensuffix ) == 0 )
> +        return true;
> +    else
> +        return false;
> +}
> +
> +
> +/**
> + * Function to fill video_format_t fields for an elementary stream
> + * @param fmt video format structure
> + * @param width picture width
> + * @param height picture height
> + * @param frame_rate_num video frame rate numerator
> + * @param frame_rate_denom video frame rate denominator
> + */
> +void fillVideoFmt( video_format_t * fmt, unsigned int width, unsigned int
> height, unsigned int frame_rate_num, unsigned int frame_rate_denom ) +{
> +    fmt->i_width = width;
> +    fmt->i_height = height;
> +    /* As input are square pixels let VLC  or decoder fix SAR, origin,
> +     * and visible area */
> +    fmt->i_frame_rate = frame_rate_num;
> +    fmt->i_frame_rate_base = frame_rate_denom;
> +}
> +
> +/**
> + * Function to free memory in parserAssetmapXML function
> + * @param reader xmlTextReaderPtr object
> + */
> +static void freeMemXML( xml_reader_t *p_xmlReader, xml_t *p_xml, stream_t
> *p_stream ) +{
> +    if( p_xmlReader )
> +        xml_ReaderDelete( p_xmlReader );
> +    if( p_stream )
> +        stream_Delete( p_stream );
> +    if( p_xml )
> +        xml_Delete( p_xml );
> +}
> +
> +/**
> + * Function to free memory in case of error or when closing the module
> + * @param p_demux DCP access-demux
> + */
> +void freeMem( demux_t *p_demux )
> +{
> +    demux_sys_t *p_sys = p_demux->p_sys;
> +    /* close the files */
> +    switch( p_sys->PictureEssType )
> +    {
> +        case ESS_UNKNOWN:
> +            break;
> +        case ESS_JPEG_2000:
> +            if( p_sys->p_PicMXFReader )
> +                p_sys->p_PicMXFReader->Close();
> +            break;
> +        case ESS_JPEG_2000_S:
> +            if( p_sys->p_PicMXFSReader )
> +                p_sys->p_PicMXFSReader->Close();
> +            break;
> +        case ESS_MPEG2_VES:
> +            if( p_sys->p_VideoMXFReader )
> +                p_sys->p_VideoMXFReader->Close();

This being C++, I would use virtual base class but well...

> +            break;
> +        default:
> +            break;
> +    }
> +    if( p_sys->p_AudioMXFReader )
> +        p_sys->p_AudioMXFReader->Close();
> +
> +    delete( p_demux->p_sys );
> +}
> +
> +
> +/**************************************************************************
> *** + * DCP init
> +
> ***************************************************************************
> **/ +
> +/**
> + * Function to handle the operations with the DCP directory.
> + * @param p_demux Demux pointer.
> + * @return Integer according to the success or not of the process.
> + */
> +int dcpInit ( demux_t *p_demux )
> +{
> +    int retval;
> +    /* Allocate internal state */
> +    demux_sys_t *p_sys = new ( nothrow ) demux_sys_t();
> +    if( unlikely( p_sys == NULL ) )
> +        return VLC_ENOMEM;
> +    p_demux->p_sys = p_sys;
> +
> +    /* Allocate DCP object */
> +    dcp_t *p_dcp = new ( nothrow ) dcp_t;
> +    if( unlikely( p_dcp == NULL ) )
> +        return VLC_ENOMEM;
> +
> +    p_sys->p_dcp = p_dcp;
> +
> +    p_dcp->path = p_demux->psz_file;
> +    /* We check if there is a "/" at the end of the path */
> +    if( !endsWith( p_demux->psz_file, "/" ) )
> +    {
> +        try
> +        {
> +            p_dcp->path.append( "/" );
> +        }
> +        catch(...)
> +        {
> +            msg_Err( p_demux, "String handling failed" );
> +            return VLC_EGENERIC;
> +        }
> +    }
> +
> +    /* Parsing XML files to get audio and video files */
> +    msg_Dbg( p_demux, "parsing XML files..." );
> +    if( ( retval = parserXML( p_demux ) ) )
> +        return retval;
> +    msg_Dbg(p_demux, "parsing XML files done");
> +
> +    msg_Dbg( p_demux, "path = %s", p_sys->p_dcp->path.c_str() );
> +    msg_Dbg( p_demux, "ASSETMAP = %s", p_sys->p_dcp->assetmapURI );
> +    msg_Dbg( p_demux, "CPL = %s", p_sys->p_dcp->cplfileURI );
> +    msg_Dbg( p_demux, "PKL = %s", p_sys->p_dcp->pklfile.c_str() );
> +    msg_Dbg( p_demux, "video = %s", p_sys->p_dcp->videofile.c_str() );
> +    msg_Dbg( p_demux, "audio = %s", p_sys->p_dcp->audiofile.c_str() );
> +
> +    return VLC_SUCCESS;
> +}
> +
> +
> +/**************************************************************************
> *** + * functions for XML parsing
> +
> ***************************************************************************
> **/ +
> +/**
> + * Function to create XML parser - using VLC libxml2 wrapper
> + * @param p_stream stream used to access XML file
> + * @param p_xml object used to create XML Reader
> + * @param p_xmlReader object used to read XML file
> + */
> +static int initXMLParser( demux_t *p_demux, char *filePath, stream_t
> **p_stream, xml_t **p_xml, xml_reader_t **p_xmlReader ) +{
> +    *p_xml = xml_Create( p_demux );
> +    if( ! *p_xml )
> +        return VLC_EGENERIC;
> +
> +    /* create the stream to read from */
> +    *p_stream = stream_UrlNew( p_demux, filePath );
> +    if( ! *p_stream )
> +        return VLC_EGENERIC;
> +
> +    /* init XML reader */
> +    *p_xmlReader = xml_ReaderCreate( *p_xml, *p_stream );
> +    if( ! *p_xmlReader )
> +        return VLC_EGENERIC;
> +
> +    return VLC_SUCCESS;
> +}
> +
> +/**
> + * Function to retrieve the path to the ASSETMAP file.
> + * @param p_demux DCP access_demux.
> + */
> +static int assetmapPath( demux_t * p_demux )
> +{
> +    DIR *dir = NULL;
> +    struct dirent *ent = NULL;
> +    string result;
> +
> +    if( ( dir = opendir ( p_demux->psz_file ) ) != NULL )
> +    {
> +        /* print all the files and directories within directory */
> +        while( ( ent = readdir ( dir ) ) != NULL )
> +        {
> +            if( strcasecmp( "assetmap", ent->d_name ) == 0 || strcasecmp(
> "assetmap.xml", ent->d_name ) == 0 ) +            {
> +                /* copy of "path" in "res" */
> +                result = p_demux->psz_file;
> +                try
> +                {
> +                    result.append( ent->d_name );
> +                }
> +                catch(...)
> +                {
> +                    msg_Err( p_demux, "String handling failed" );
> +                    return VLC_EGENERIC;
> +                }
> +                break;
> +            }
> +        }
> +        closedir( dir );
> +    }
> +    else
> +    {
> +        msg_Err( p_demux, "Could not open the directory: %s",
> p_demux->psz_file ); +        return VLC_EGENERIC;
> +    }
> +    /* if no assetmap file */
> +    if( result.empty() )
> +    {
> +        msg_Err( p_demux, "No ASSETMAP found in the directory: %s",
> p_demux->psz_file ); +        return VLC_EGENERIC;
> +    }
> +
> +    /* We convert the ASSETMAP path into URI (transformation needed later,
> when reading with XML Reader) +     * and copy it into p_dcp structure */
> +    p_demux->p_sys->p_dcp->assetmapURI = vlc_path2uri( result.c_str(),
> "file" ); +    if( unlikely( p_demux->p_sys->p_dcp->assetmapURI == NULL ) )
> +        return VLC_ENOMEM;
> +
> +    return VLC_SUCCESS;
> +}
> +
> +/**
> + * Function to parse the assetmap file in order to get CPL file path, PKL
> file path and + * to store UID/Path of files described in the ASSETMAP XML
> file. + * @param p_demux DCP access_demux.
> + */
> +int parserAssetmapXML ( demux_t * p_demux )
> +{
> +    dcp_t *p_dcp = p_demux->p_sys->p_dcp;
> +    int type = 0;
> +    const char* node = NULL;
> +    int packinglist = 0;
> +    int file_number = 0;
> +    int asset_list = 0;
> +    string filepath;
> +    stream_t *p_stream = NULL;
> +    xml_t *p_xml = NULL;
> +    xml_reader_t *p_xmlReader = NULL;
> +
> +    /* init XML parser */
> +    if( initXMLParser( p_demux, p_dcp->assetmapURI, &p_stream, &p_xml,
> &p_xmlReader ) ) +    {
> +        msg_Err( p_demux, "Failed to initialize XML parser" );
> +        goto error;
> +    }
> +
> +    /* reading XML file ( node by node ) */
> +    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 ) ) +        {
> +            asset_list = 1;
> +            continue;
> +        }
> +
> +        /* When we are in AssetList part */
> +        if( asset_list == 1 )
> +        {
> +            /* Set the UID of the file */
> +            if( ( type == XML_READER_STARTELEM ) && ( strcasecmp( node,
> "Id" ) == 0 ) ) +            {
> +                if( ( type = xml_ReaderNextNode( p_xmlReader, &node ) ) !=
> XML_READER_TEXT ) +                {
> +                    msg_Err( p_demux, "Id missing in ASSETMAP!" );
> +                    goto error;
> +                }
> +                else
> +                {
> +                    p_dcp->files[ file_number ] = new ( nothrow ) file_t;
> +                    if( !p_dcp->files[ file_number ] )
> +                    {
> +                        msg_Err( p_demux, "Could not alloc variable." );
> +                        goto error;
> +                    }
> +                    if( node != NULL )
> +                        p_dcp->files[file_number]->id = node;
> +                    continue;
> +                }
> +            }
> +
> +            /* It determines if it is PKL File or not */
> +            /* For PKL File, we have : <PackingList>true</PackingList> */
> +            /* This tag seems to be used only for PKL file */
> +            if( ( type == XML_READER_STARTELEM ) && ( strcasecmp ( node,
> "PackingList" ) == 0 ) ) +            {
> +                packinglist = 1; /* next path info will be for PKL file */
> +                continue;
> +            }
> +
> +            /* Set the Path of the file */
> +            /* If the file is an XML file, it is the PKL file or the CPL
> file */ +            if( ( type == XML_READER_STARTELEM ) && ( strcasecmp(
> node, "Path" ) == 0 ) ) +            {
> +                if( ( type = xml_ReaderNextNode( p_xmlReader, &node ) ) !=
> XML_READER_TEXT ) +                {
> +                    msg_Err( p_demux, "Path missing in ASSETMAP" );
> +                    goto error;
> +                }
> +                else
> +                {
> +                    filepath = p_dcp->path + node;
> +                    if( endsWith( node, ".xml" ) )
> +                    {
> +                        if( packinglist == 1 )
> +                        {
> +                            /* it is PKL file name */
> +                            p_dcp->pklfile = filepath;
> +                            p_dcp->files[file_number]->path = filepath;
> +                            packinglist = 0;
> +                        }
> +                        else
> +                        {
> +                            /* it is CPL file name */
> +                            p_dcp->cplfileURI = vlc_path2uri(
> filepath.c_str(), "file" ); +                           
> p_dcp->files[file_number]->path = filepath; +                        }
> +                    }
> +                    else
> +                    {
> +                        /* it is an other file (MXF in theory) */
> +                        p_dcp->files[file_number]->path = filepath;
> +                    }
> +                    file_number++;
> +                }
> +            }
> +        }
> +    }
> +    if( asset_list == 0 )
> +    {
> +        msg_Err( p_demux, "Could not find AssetList tag in ASSETMAP" );
> +        goto error;
> +    }
> +
> +    if( !p_dcp->cplfileURI )
> +    {
> +        msg_Err( p_demux, "Could not find CPL file in ASSETMAP" );
> +        goto error;
> +    }
> +    if( p_dcp->pklfile.empty() )
> +    {
> +        msg_Err( p_demux, "Could not find PKL file in ASSETMAP" );
> +        goto error;
> +    }
> +
> +    /* Set the number of files described in ASSETMAP file */
> +    p_dcp->nb_files = file_number;
> +
> +    /* free memory */
> +    freeMemXML( p_xmlReader, p_xml, p_stream );
> +    return VLC_SUCCESS;
> +
> +error:
> +    freeMemXML( p_xmlReader, p_xml, p_stream );
> +    return VLC_EGENERIC;
> +}
> +
> +/**
> + * Function to parse the CPL file in order to retrieve UID of video and
> audio files. + * When it is done, we can determine path to video and audio
> files using information + * about files described in ASSETMAP file
> + * @param p_demux DCP access_demux.
> + */
> +int parserCplXML ( demux_t * p_demux )
> +{
> +    dcp_t *p_dcp = p_demux->p_sys->p_dcp;
> +    int type = 0;
> +    bool found = false;
> +    const char *node = NULL;
> +    stream_t *p_stream = NULL;
> +    xml_t *p_xml = NULL;
> +    xml_reader_t *p_xmlReader = NULL;
> +
> +    /* init XML reader */
> +    if( initXMLParser( p_demux, p_dcp->cplfileURI, &p_stream, &p_xml,
> &p_xmlReader ) ) +    {
> +        msg_Err( p_demux, "Failed to initialize XML parser" );
> +        goto error;
> +    }
> +
> +    /* Read XML file node by node */
> +    msg_Dbg( p_demux, "reading CPL file..." );
> +    while( ( type = xml_ReaderNextNode( p_xmlReader, &node ) ) > 0 )
> +    {
> +        /* MainPicture data */
> +        if( ( type == XML_READER_STARTELEM) && ( strcasecmp( node,
> "MainPicture" ) == 0 || strcasecmp( node, "MainStereoscopicPicture" ) == 0
> ) ) +        {
> +            /* searching for the Id of the picture file */
> +            found = false;
> +            while( ( type = xml_ReaderNextNode( p_xmlReader, &node ) ) > 0
> ) +            {
> +                if( ( type == XML_READER_STARTELEM ) && ( strcasecmp( node,
> "Id" ) == 0 ) ) +                {
> +                    if( ( type = xml_ReaderNextNode( p_xmlReader, &node ) )
> != XML_READER_TEXT ) +                    {
> +                        msg_Err( p_demux, "MainPicture Id missing in CPL!"
> ); +                        goto error;
> +                    }
> +                    else
> +                    {
> +                        for( int i = 0; i < p_dcp->nb_files; i++ )
> +                        {
> +                            if( p_dcp->files[i]->id.compare( node ) == 0 )
> +                            {
> +                                p_dcp->videofile = p_dcp->files[i]->path;
> +                                found = true;
> +                                break;
> +                            }
> +                        }
> +                        if( found )
> +                            break;
> +                    }
> +                }
> +            }
> +        }
> +
> +        /* MainSound data */
> +        if( ( type == XML_READER_STARTELEM) && ( strcasecmp( node,
> "MainSound" ) == 0 ) ) +        {
> +            /* searching for the Id of the audio file */
> +            found = false;
> +            while( ( type = xml_ReaderNextNode( p_xmlReader, &node ) ) > 0
> ) +            {
> +                if( ( type == XML_READER_STARTELEM ) && ( strcasecmp( node,
> "Id" ) == 0 ) ) +                {
> +                    if( ( type = xml_ReaderNextNode( p_xmlReader, &node ) )
>  != XML_READER_TEXT ) +                    {
> +                        msg_Err( p_demux, "MainSound Id missing in CPL!" );
> +                        goto error;
> +                    }
> +                    else
> +                    {
> +                        for( int i = 0; i < p_dcp->nb_files; i++ )
> +                        {
> +                            if( p_dcp->files[i]->id.compare( node ) == 0 )
> +                            {
> +                                p_dcp->audiofile = p_dcp->files[i]->path;
> +                                found = true;
> +                                break;
> +                            }
> +                        }
> +                        if( found )
> +                            break;
> +                    }
> +                }
> +            }
> +        }
> +    }
> +
> +    if( p_dcp->videofile.empty() )
> +    {
> +        msg_Err( p_demux, "Could not find video file in ASSETMAP" );
> +        goto error;
> +    }
> +
> +    if( p_dcp->audiofile.empty() )
> +    {
> +        msg_Err( p_demux, "Could not find audio file in ASSETMAP" );
> +        goto error;
> +    }
> +
> +    /* free memory */
> +    freeMemXML( p_xmlReader, p_xml, p_stream );
> +    return VLC_SUCCESS;
> +
> +error:
> +    freeMemXML( p_xmlReader, p_xml, p_stream );
> +    return VLC_EGENERIC;
> +}
> +
> +
> +/**
> + * Function which parses XML files in DCP directory in order to get video
> and audio files + * @param p_demux Demux pointer.
> + * @return Integer according to the success or not of the operation
> + */
> +int parserXML ( demux_t * p_demux )
> +{
> +    int retval;
> +    /* We get the ASSETMAP file path */
> +    if( assetmapPath( p_demux ) )
> +        return VLC_EGENERIC;
> +
> +    /* We parse the ASSETMAP File in order to get CPL File path, PKL File
> path +     and to store UID/Path of all files in DCP directory (except
> ASSETMAP file) */ +    if( ( retval = parserAssetmapXML( p_demux ) ) )
> +        return retval;
> +
> +    /* We parse the CPL File : in order to retrieve video and audio files
> +     according to UID of files described in CPL XML file */
> +    if( ( retval = parserCplXML( p_demux ) ) )
> +        return retval;
> +
> +    return VLC_SUCCESS; /* TODO : perform checking on XML parsing */
> +}
> +
> +
> +
-- 
Rémi Denis-Courmont
http://www.remlab.net/





More information about the vlc-devel mailing list