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

Nicolas Bertrand nicoinattendu at gmail.com
Mon Dec 2 14:01:55 CET 2013


This version only support 1-Reel-per-track DCPs, like trailers

---
 configure.ac                     |   17 +
 modules/access/Makefile.am       |    7 +
 modules/access/dcp/dcp.cpp       |  756 ++++++++++++++++++++++
 modules/access/dcp/dcpparser.cpp | 1312 ++++++++++++++++++++++++++++++++++++++
 modules/access/dcp/dcpparser.h   |  293 +++++++++
 5 files changed, 2385 insertions(+)
 create mode 100644 modules/access/dcp/dcp.cpp
 create mode 100644 modules/access/dcp/dcpparser.cpp
 create mode 100644 modules/access/dcp/dcpparser.h

diff --git a/configure.ac b/configure.ac
index 5f7ed24..e6951dc 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1918,6 +1918,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 "x${enable_dcp}" != "no"], [
+  AC_LANG_PUSH(C++)
+  AC_CHECK_HEADERS( [[AS@&t at _DCP.h]],
+    [have_asdcp="yes"],
+    [AS_IF( [test "x${enable_dcp}" = "yes"],
+      [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/Makefile.am b/modules/access/Makefile.am
index 6b48799..27193a1 100644
--- a/modules/access/Makefile.am
+++ b/modules/access/Makefile.am
@@ -9,6 +9,13 @@ AM_CPPFLAGS += -I$(srcdir)/access
 libattachment_plugin_la_SOURCES = access/attachment.c
 access_LTLIBRARIES += libattachment_plugin.la
 
+libdcp_plugin_la_SOURCES = access/dcp/dcpparser.h access/dcp/dcp.cpp access/dcp/dcpparser.cpp
+libdcp_plugin_la_CPPFLAGS = $(AM_CPPFLAGS)
+libdcp_plugin_la_LIBADD = $(AM_LIBADD) -lasdcp
+if HAVE_ASDCP
+access_LTLIBRARIES += libdcp_plugin.la
+endif
+
 libfilesystem_plugin_la_SOURCES = access/fs.h access/file.c access/directory.c access/fs.c
 libfilesystem_plugin_la_CPPFLAGS = $(AM_CPPFLAGS)
 if HAVE_WIN32
diff --git a/modules/access/dcp/dcp.cpp b/modules/access/dcp/dcp.cpp
new file mode 100644
index 0000000..40c3a55
--- /dev/null
+++ b/modules/access/dcp/dcp.cpp
@@ -0,0 +1,756 @@
+/*****************************************************************************
+ * Copyright (C) 2012-2013 VLC authors and VideoLAN
+ *
+ * Authors:
+ *          Nicolas Bertrand <nico at isf.cc>
+ *          Simona-Marinela Prodea <simona dot marinela dot prodea at gmail dot com>
+ *          Jean-Baptiste Kempf <jb at videolan.org>
+ *          Pierre Villard <pierre dot villard dot fr at gmail dot com>
+ *          Claire Etienne
+ *          Aurélie Sbinné
+ *          Samuel Kerjose
+ *          Julien Puyobro
+ *
+ * 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
+
+#define __STDC_CONSTANT_MACROS 1
+
+/* 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>
+
+#include "dcpparser.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 module" ) )
+    set_capability( "access_demux", 0 )
+    set_category( CAT_INPUT )
+    set_subcategory( SUBCAT_INPUT_ACCESS )
+    set_callbacks( Open, Close )
+vlc_module_end()
+
+//! Kind of MXF MEDIA TYPE
+typedef enum MxfMedia_t {
+    MXF_UNKNOWN = 0,
+    MXF_PICTURE,
+    MXF_AUDIO,
+} MxfMedia_t;
+
+/* 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;
+
+    mtime_t i_pts;
+
+    demux_sys_t():
+        PictureEssType ( ESS_UNKNOWN ),
+        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 ),
+        frame_no( 0 ) {};
+
+    ~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;
+        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 parseXML ( 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 CloseDcpAndMxf( 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;
+    es_format_t video_format, audio_format;
+    int retval;
+
+    if( !p_demux->psz_file )
+        return VLC_EGENERIC;
+
+    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 ) ) {
+        delete  p_sys;
+        return VLC_ENOMEM;
+    }
+    p_sys->p_dcp = p_dcp;
+
+
+    /* handle the DCP directory, saving the paths for audio and video file, returning error if unsuccessful */
+    if( ( retval = dcpInit( p_demux ) ) )
+        goto error;
+
+
+    /* 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() );
+            retval = VLC_EGENERIC;
+            goto error;
+
+        case ESS_JPEG_2000:
+        case ESS_JPEG_2000_S:
+            JP2K::PictureDescriptor *p_PicDesc;
+
+            p_PicDesc = p_sys->p_PicDesc = new ( nothrow ) JP2K::PictureDescriptor();
+            if ( !p_PicDesc ) {
+                retval = VLC_ENOMEM;
+                goto error;
+            }
+            if (p_sys->PictureEssType == ESS_JPEG_2000_S) {     /* 3D JPEG2000 */
+                JP2K::MXFSReader        *p_PicMXFSReader;
+                p_PicMXFSReader = p_sys->p_PicMXFSReader = new ( nothrow ) JP2K::MXFSReader();
+
+                if( !p_PicMXFSReader) {
+                    retval = VLC_ENOMEM;
+                    goto error;
+                }
+                if( !ASDCP_SUCCESS( p_PicMXFSReader->OpenRead( p_sys->p_dcp->videofile.c_str() ) ) ) {
+                    msg_Err( p_demux, "File %s could not be opened with ASDCP", p_sys->p_dcp->videofile.c_str() );
+                    retval = VLC_EGENERIC;
+                    goto error;
+                }
+
+                p_PicMXFSReader->FillPictureDescriptor( *p_PicDesc );
+            } else {                                            /* 2D JPEG2000 */
+                JP2K::MXFReader         *p_PicMXFReader;
+                p_PicMXFReader = p_sys->p_PicMXFReader = new ( nothrow ) JP2K::MXFReader();
+                if( !p_PicMXFReader ) {
+                    retval = VLC_ENOMEM;
+                    goto error;
+                }
+                if( !ASDCP_SUCCESS( p_PicMXFReader->OpenRead( p_sys->p_dcp->videofile.c_str() ) ) ) {
+                    msg_Err( p_demux, "File %s could not be opened with ASDCP",
+                                    p_sys->p_dcp->videofile.c_str() );
+                    retval = VLC_EGENERIC;
+                    goto error;
+                }
+
+                p_PicMXFReader->FillPictureDescriptor( *p_PicDesc );
+            }
+            es_format_Init( &video_format, VIDEO_ES, VLC_CODEC_JPEG2000 );
+            fillVideoFmt( &video_format.video, p_PicDesc->StoredWidth, p_PicDesc->StoredHeight, p_PicDesc->EditRate.Numerator, p_PicDesc->EditRate.Denominator );
+
+            p_sys->p_PicDesc = p_PicDesc;
+            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:
+            MPEG2::MXFReader        *p_VideoMXFReader;
+            MPEG2::VideoDescriptor  *p_VideoDesc;
+
+            p_VideoMXFReader = p_sys->p_VideoMXFReader = new ( nothrow ) MPEG2::MXFReader();
+            p_VideoDesc = p_sys->p_VideoDesc = new ( nothrow ) MPEG2::VideoDescriptor();
+
+            if( !p_VideoMXFReader || !p_VideoDesc ) {
+                retval = VLC_ENOMEM;
+                goto error;
+            }
+
+            if( !ASDCP_SUCCESS( p_VideoMXFReader->OpenRead( p_sys->p_dcp->videofile.c_str() ) ) ) {
+                msg_Err( p_demux, "File %s could not be opened with ASDCP", p_sys->p_dcp->videofile.c_str() );
+                retval = VLC_EGENERIC;
+                goto error;
+            }
+
+            p_VideoMXFReader->FillVideoDescriptor( *p_VideoDesc );
+
+            es_format_Init( &video_format, VIDEO_ES, VLC_CODEC_MPGV );
+            fillVideoFmt( &video_format.video, p_VideoDesc->StoredWidth, p_VideoDesc->StoredHeight, p_VideoDesc->EditRate.Numerator, p_VideoDesc->EditRate.Denominator );
+
+            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" );
+            retval = VLC_EGENERIC;
+            goto error;
+    }
+
+    if ( (p_sys->frame_rate_num == 0) || (p_sys->frame_rate_denom == 0) ) {
+        msg_Err(p_demux, "Invalid frame rate (%i/%i)",
+                p_sys->frame_rate_num, p_sys->frame_rate_denom);
+        retval = VLC_EGENERIC;
+        goto error;
+    }
+
+    if( ( p_sys->p_video_es = es_out_Add( p_demux->out, &video_format ) ) == NULL ) {
+        msg_Err( p_demux, "Failed to add video es" );
+        retval = VLC_EGENERIC;
+        goto error;
+    }
+
+    /* Open audio file */
+    EssenceType_t AudioEssType;
+    EssenceType( p_sys->p_dcp->audiofile.c_str(), AudioEssType );
+    if ( (AudioEssType == ESS_PCM_24b_48k) || (AudioEssType == ESS_PCM_24b_96k) ) {
+        PCM::MXFReader          *p_AudioMXFReader;
+        PCM::AudioDescriptor    *p_AudioDesc;
+
+        p_AudioMXFReader = p_sys->p_AudioMXFReader = new ( nothrow ) PCM::MXFReader();
+        p_AudioDesc = p_sys->p_AudioDesc = new ( nothrow ) PCM::AudioDescriptor();
+
+        if( !p_AudioMXFReader || !p_AudioDesc  ){
+            retval = VLC_ENOMEM;
+            goto error;
+        }
+
+        if( !ASDCP_SUCCESS( p_AudioMXFReader->OpenRead( p_sys->p_dcp->audiofile.c_str() ) ) ) {
+            msg_Err( p_demux, "File %s could not be opened with ASDCP",
+                            p_sys->p_dcp->audiofile.c_str() );
+            retval = VLC_EGENERIC;
+            goto error;
+        }
+
+        p_AudioMXFReader->FillAudioDescriptor( *p_AudioDesc );
+
+        es_format_Init( &audio_format, AUDIO_ES, VLC_CODEC_S24L );
+        if( p_AudioDesc->AudioSamplingRate.Denominator != 0 )
+            audio_format.audio.i_rate =
+                  p_AudioDesc->AudioSamplingRate.Numerator
+                / p_AudioDesc->AudioSamplingRate.Denominator;
+        else if ( AudioEssType == ESS_PCM_24b_96k )
+            audio_format.audio.i_rate = 96000;
+        else
+            audio_format.audio.i_rate = 48000;
+
+        audio_format.audio.i_bitspersample = p_AudioDesc->QuantizationBits;
+        audio_format.audio.i_blockalign    = p_AudioDesc->BlockAlign;
+        audio_format.audio.i_channels      = p_AudioDesc->ChannelCount;
+
+        if( ( p_sys->p_audio_es = es_out_Add( p_demux->out, &audio_format ) ) == NULL ) {
+            msg_Err( p_demux, "Failed to add audio es" );
+            retval = VLC_EGENERIC;
+            goto error;
+        }
+    } else {
+        msg_Err( p_demux, "The file %s is not a supported AS_DCP essence container",
+                          p_sys->p_dcp->audiofile.c_str() );
+        retval = VLC_EGENERIC;
+        goto error;
+    }
+
+
+    p_sys->p_out = p_demux->out;
+    p_demux->pf_demux = Demux;
+    p_demux->pf_control = Control;
+
+    return VLC_SUCCESS;
+error:
+    CloseDcpAndMxf( p_demux );
+    return retval;
+}
+
+
+/*****************************************************************************
+ * Close: module destroy function
+ *****************************************************************************/
+static inline void Close( vlc_object_t *obj )
+{
+    demux_t *p_demux = ( demux_t* ) obj;
+    CloseDcpAndMxf( p_demux );
+}
+
+
+
+/*****************************************************************************
+ * 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;
+    uint32_t i_audio_buffer = PCM::CalcFrameBufferSize(*p_sys->p_AudioDesc);
+    PCM::FrameBuffer   AudioFrameBuff(i_audio_buffer);
+
+    if( i == p_sys->frames_total )
+        return 0;
+
+    /* video frame */
+    switch( p_sys->PictureEssType )
+    {
+        case ESS_JPEG_2000:
+        case ESS_JPEG_2000_S:{
+            JP2K::FrameBuffer  PicFrameBuff(FRAME_BUFFER_SIZE);
+            if ( ( p_video_frame = block_Alloc( FRAME_BUFFER_SIZE )) == NULL )
+                goto error;
+
+            if ( ! ASDCP_SUCCESS(
+                    PicFrameBuff.SetData(p_video_frame->p_buffer, FRAME_BUFFER_SIZE)) )
+                goto error_asdcp;
+            if ( p_sys->PictureEssType == ESS_JPEG_2000_S ) {
+                if ( ! ASDCP_SUCCESS(
+                        p_sys->p_PicMXFSReader->ReadFrame(i + p_sys->p_dcp->i_video_entry, JP2K::SP_LEFT, PicFrameBuff, 0, 0)) ) {
+                    PicFrameBuff.SetData(0,0);
+                    goto error_asdcp;
+                }
+             } else {
+                if ( ! ASDCP_SUCCESS(
+                        p_sys->p_PicMXFReader->ReadFrame(i + p_sys->p_dcp->i_video_entry, PicFrameBuff, 0, 0)) ) {
+                    PicFrameBuff.SetData(0,0);
+                    goto error_asdcp;
+                }
+            }
+            p_video_frame->i_buffer = PicFrameBuff.Size();
+            break;
+        }
+        case ESS_MPEG2_VES: {
+            MPEG2::FrameBuffer VideoFrameBuff(FRAME_BUFFER_SIZE);
+            if ( ( p_video_frame = block_Alloc( FRAME_BUFFER_SIZE )) == NULL )
+                goto error;
+
+            if ( ! ASDCP_SUCCESS(
+                    VideoFrameBuff.SetData(p_video_frame->p_buffer, FRAME_BUFFER_SIZE)) )
+                goto error_asdcp;
+
+            if ( ! ASDCP_SUCCESS(
+                    p_sys->p_VideoMXFReader->ReadFrame(i + p_sys->p_dcp->i_video_entry, VideoFrameBuff, 0, 0)) ) {
+                VideoFrameBuff.SetData(0,0);
+                goto error_asdcp;
+            }
+
+            p_video_frame->i_buffer = VideoFrameBuff.Size();
+            break;
+        }
+        default:
+            msg_Err( p_demux, "Unrecognized video format" );
+            goto error;
+    }
+
+    p_video_frame->i_length = CLOCK_FREQ * p_sys->frame_rate_denom / p_sys->frame_rate_num;
+    p_video_frame->i_pts = CLOCK_FREQ * p_sys->frame_no * p_sys->frame_rate_denom / p_sys->frame_rate_num;
+
+    /* audio frame */
+    if ( ( p_audio_frame = block_Alloc( i_audio_buffer )) == NULL ) {
+        goto error;
+    }
+    if ( ! ASDCP_SUCCESS(
+            AudioFrameBuff.SetData(p_audio_frame->p_buffer, i_audio_buffer)) ) {
+        goto error_asdcp;
+    }
+
+    if ( ! ASDCP_SUCCESS(
+            p_sys->p_AudioMXFReader->ReadFrame(i + p_sys->p_dcp->i_audio_entry, AudioFrameBuff, 0, 0)) ) {
+        AudioFrameBuff.SetData(0,0);
+        goto error_asdcp;
+    }
+
+    p_audio_frame->i_buffer = AudioFrameBuff.Size();
+    p_audio_frame->i_length = CLOCK_FREQ * p_sys->frame_rate_denom / p_sys->frame_rate_num;
+    p_audio_frame->i_pts = CLOCK_FREQ * p_sys->frame_no * p_sys->frame_rate_denom / p_sys->frame_rate_num;
+    /* Video is the main pts */
+    if ( p_audio_frame->i_pts != p_video_frame->i_pts ) {
+        msg_Err( p_demux, "Audio and video frame pts are not in sync" );
+    }
+
+    p_sys->i_pts = p_video_frame->i_pts;
+    es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_sys->i_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;
+
+error_asdcp:
+    msg_Err( p_demux, "Couldn't read frame with ASDCP");
+error:
+    if (p_video_frame)
+        block_Release(p_video_frame);
+    if (p_audio_frame)
+        block_Release(p_audio_frame);
+    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;
+            break;
+
+        case DEMUX_SET_PAUSE_STATE:
+            break;
+
+        case DEMUX_CAN_SEEK:
+            pb = (bool *)va_arg( args, bool * );
+            if( p_sys->PictureEssType != ESS_MPEG2_VES )
+                *pb = true;
+            else
+                *pb = false;
+            break;
+
+        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_Warn( p_demux, "Total number of frames is 0" );
+            break;
+
+        case DEMUX_SET_POSITION:
+            f = ( double ) va_arg ( args, double );
+            p_sys->frame_no = (int) ( f * p_sys->frames_total );
+            break;
+
+        case DEMUX_GET_LENGTH:
+            pi64 = ( int64_t* ) va_arg ( args, int64_t* );
+            *pi64 = (int) ( ( p_sys->frames_total * p_sys->frame_rate_denom / p_sys->frame_rate_num ) * CLOCK_FREQ );
+            break;
+
+        case DEMUX_GET_TIME:
+            pi64 = ( int64_t* ) va_arg ( args, int64_t* );
+            *pi64 = p_sys->i_pts >= 0 ? p_sys->i_pts : 0;
+            break;
+
+        case DEMUX_SET_TIME:
+            i64 = ( int64_t ) va_arg ( args, int64_t );
+            msg_Warn( p_demux, "DEMUX_SET_TIME"  );
+            p_sys->frame_no = i64 * p_sys->frame_rate_num / ( CLOCK_FREQ * p_sys->frame_rate_denom );
+            p_sys->i_pts= i64;
+            es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_sys->i_pts);
+            es_out_Control( p_demux->out, ES_OUT_SET_NEXT_DISPLAY_TIME, ( mtime_t ) i64 );
+            break;
+        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 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 case of error or when closing the module
+ * @param p_demux DCP access-demux
+ */
+void CloseDcpAndMxf( 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();
+            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;
+
+    demux_sys_t *p_sys = p_demux->p_sys;
+    dcp_t *p_dcp = p_sys->p_dcp;
+
+    p_dcp->path = p_demux->psz_file;
+    /* Add a '/' in end of path if needed */
+    if ( *(p_dcp->path).rbegin() != '/')
+        p_dcp->path.append( "/" );
+
+    /* Parsing XML files to get audio and video files */
+    msg_Dbg( p_demux, "parsing XML files..." );
+    if( ( retval = parseXML( p_demux ) ) )
+        return retval;
+
+    msg_Dbg(p_demux, "parsing XML files done");
+
+#ifndef NDEBUG
+    msg_Dbg( p_demux, "path = %s", p_sys->p_dcp->path.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() );
+#endif
+
+    return VLC_SUCCESS;
+}
+
+
+/*****************************************************************************
+ * functions for XML parsing
+ *****************************************************************************/
+
+/**
+ * Function to retrieve the path to the ASSETMAP file.
+ * @param p_demux DCP access_demux.
+ */
+static string assetmapPath( demux_t * p_demux )
+{
+    DIR *dir = NULL;
+    struct dirent *ent = NULL;
+    dcp_t *p_dcp = p_demux->p_sys->p_dcp;
+    string result;
+
+    if( ( dir = opendir (p_dcp->path.c_str() ) ) != 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_dcp->path;
+                try
+                {
+                    result.append( ent->d_name );
+                }
+                catch(...)
+                {
+                    msg_Err( p_demux, "String handling failed" );
+                    closedir( dir );
+                    return NULL;
+                }
+                break;
+            }
+        }
+        closedir( dir );
+    }
+    else
+        msg_Err( p_demux, "Could not open the directory: %s", p_dcp->path.c_str() );
+
+    /* if no assetmap file */
+    if( result.empty() )
+        msg_Err( p_demux, "No ASSETMAP found in the directory: %s", p_dcp->path.c_str() );
+
+    return result;
+}
+
+
+/**
+ * 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 parseXML ( demux_t * p_demux )
+{
+    int retval;
+
+    string assetmap_path = assetmapPath( p_demux );
+    /* We get the ASSETMAP file path */
+    if( assetmap_path.empty() )
+        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) */
+    AssetMap *assetmap = new AssetMap( p_demux, assetmap_path, p_demux->p_sys->p_dcp );
+    if( ( retval = assetmap->Parse() ) )
+        return retval;
+
+    delete assetmap;
+    return VLC_SUCCESS; /* TODO : perform checking on XML parsing */
+}
diff --git a/modules/access/dcp/dcpparser.cpp b/modules/access/dcp/dcpparser.cpp
new file mode 100644
index 0000000..4416996
--- /dev/null
+++ b/modules/access/dcp/dcpparser.cpp
@@ -0,0 +1,1312 @@
+/*****************************************************************************
+ * Copyright (C) 2013 VLC authors and VideoLAN
+ *
+ * Authors:
+ *          Nicolas Bertrand <nico at isf.cc>
+ *          Jean-Baptiste Kempf <jb at videolan.org>
+ *
+ * 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.cpp
+ * @brief Parsing of DCP XML files
+ */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+/* VLC core API headers */
+#include <vlc_common.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;
+
+    if (p_type != XML_READER_STARTELEM)
+        return -1;
+
+    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;
+}
+
+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
+ */
+int Chunk::Parse( xml_reader_t *p_xmlReader, string p_node, int p_type){
+    string node;
+    int type;
+    string s_value;
+    static const string names[] = {"Path", "VolumeIndex", "Offset",
+                               "Length"};
+    if (p_type != XML_READER_STARTELEM)
+        return -1;
+    if( p_node != "Chunk")
+        return -1;
+    /* loop on Chunks Node */
+    while( ( type = ReadNextNode( p_xmlReader, node ) ) > 0 ) {
+        switch (type) {
+            case XML_READER_STARTELEM:
+            {
+                ChunkTag_t chunk_tag = CHUNK_UNKNOWN;
+                for(ChunkTag_t i = CHUNK_UNKNOWN; i < CHUNK_LENGTH; i = ChunkTag_t(i+1)) {
+                    if( node == names[i]) {
+                        chunk_tag = ChunkTag_t(i+1);
+                        if ( ReadEndNode(p_xmlReader, node, type, s_value))
+                            return -1;
+                        switch (chunk_tag) {
+                            case CHUNK_PATH:
+                                this->s_path = s_value;
+                                break;
+                            case CHUNK_VOL_INDEX:
+                                this->i_vol_index = atoi(s_value.c_str());
+                                break;
+                            case CHUNK_OFFSET:
+                                this->i_offset = atoi(s_value.c_str());
+                                break;
+                            case CHUNK_LENGTH:
+                                this->i_length = atoi(s_value.c_str());
+                                break;
+                            case CHUNK_UNKNOWN:
+                            default:
+                                break;
+                        }
+                    }
+                }
+                if(chunk_tag == CHUNK_UNKNOWN)
+                    return -1;
+                break;
+            }
+            case XML_READER_TEXT:
+                s_value = node;
+                if (unlikely(node.empty()))
+                    return -1;
+                break;
+            case XML_READER_ENDELEM:
+                /* Verify if we reach Chuk endelem  */
+                if ( node == p_node) {
+                    /* verify path */
+                    if ( this->s_path.empty() ) {
+                        msg_Err(this->p_demux, "Chunk::Parse No path found");
+                        return -1;
+                    }
+                    if ( this->i_vol_index != 1 ) {
+                        msg_Err(this->p_demux, "Only one VOLINDEX suported. Patch welcome.");
+                        return -1;
+                    }
+                    /* end of Chnuk tag parse */
+                    return 0;
+                }
+                break;
+        }
+    }
+    return -1;
+}
+/*
+ * AssetMap Class
+ */
+
+AssetMap::~AssetMap() { }
+
+int AssetMap::Parse ( )
+{
+    int type = 0;
+    string node;
+
+    CPL  *cpl;
+    Reel *reel;
+    PKL  *pkl;
+    AssetList *_p_asset_list = NULL;
+
+    vector<string> pklfiles;
+
+    /* init XML parser */
+    if( this->OpenXml() ) {
+        msg_Err( p_demux, "Failed to initialize Assetmap XML parser" );
+        return -1;
+    }
+
+    /* reading ASSETMAP file to get the asset_list */
+    msg_Dbg( p_demux, "reading ASSETMAP file..." );
+    while( ( type = ReadNextNode( this->p_xmlReader, node ) ) > 0 ) {
+        if ( (type == XML_READER_STARTELEM) && ( node =="AssetList")) {
+            _p_asset_list =  new (nothrow) AssetList();
+            if ( unlikely(_p_asset_list == NULL) ) {
+                this->CloseXml();
+                return -1;
+            }
+            p_dcp->p_asset_list = _p_asset_list;
+            if (this->ParseAssetList(p_xmlReader, node, type )) {
+                this->CloseXml();
+                return -1;
+            }
+        }
+    }
+
+
+    /* Look for PKLs path */
+    if ( (_p_asset_list == NULL) ||  (_p_asset_list->size() == 0) ) {
+        msg_Err( p_demux, "Asset list empty" );
+        this->CloseXml();
+        return -1;
+    }
+
+    for (AssetList::iterator iter = _p_asset_list->begin();
+            iter != _p_asset_list->end() ; ++iter) {
+        string s_filepath;
+        s_filepath = (*iter)->getPath();
+        if (s_filepath.empty()) {
+            msg_Err( p_demux, "No path element for asset" );
+            continue;
+        }
+        /* set an absolute file path */
+        s_filepath = p_dcp->path + s_filepath;
+
+        /* case of packing list */
+        if ((*iter)->isPackingList()) {
+            pklfiles.push_back( s_filepath );
+        }
+    }
+
+    if( (pklfiles.size() == 0)  || (pklfiles[0].empty()) )
+    {
+        msg_Err( p_demux, "Could not find PKL file in ASSETMAP" );
+        this->CloseXml();
+        return -1;
+    }
+
+    /* Create the first PKL */
+    pkl = new (nothrow) PKL(p_demux, pklfiles[0], _p_asset_list, p_dcp->path);
+    if ( unlikely(pkl == NULL) ) {
+        this->CloseXml();
+        return -1;
+        }
+    if (pkl->Parse()) {
+        delete pkl;
+        this->CloseXml();
+        return -1;
+        }
+    p_dcp->pkls.push_back( pkl );
+
+    /* Now, CPL */
+    if ( pkl->FindCPLs() <= 0 ) {
+        msg_Err(p_demux, " No CPL found");
+        this->CloseXml();
+        return -1;
+    }
+    cpl = pkl->getCPL(0);
+    if( cpl == NULL ) {
+        msg_Err(p_demux, " No CPL found");
+        this->CloseXml();
+        return -1;
+    }
+    cpl->Parse();
+    reel = cpl->getReel(0);
+
+    Asset *asset;
+    /* Get picture */
+    asset = reel->getTrack(TRACK_PICTURE);
+    msg_Dbg( this->p_demux, "Video Track: %s",asset->getPath().c_str());
+    msg_Dbg( this->p_demux, "Entry point: %i",asset->getEntryPoint());
+    p_dcp->videofile = p_dcp->path + asset->getPath();
+    p_dcp->i_video_entry = asset->getEntryPoint();
+    /* Get audio */
+    asset = reel->getTrack(TRACK_SOUND);
+    msg_Dbg( this->p_demux, "Audio Track: %s",asset->getPath().c_str());
+    msg_Dbg( this->p_demux, "Entry point: %i",asset->getEntryPoint());
+    p_dcp->audiofile = p_dcp->path + asset->getPath();
+    p_dcp->i_audio_entry = asset->getEntryPoint();
+
+    /* free memory */
+    CloseXml();
+    return VLC_SUCCESS;
+}
+
+
+
+/*
+ * Asset Class
+ */
+Asset::~Asset() {}
+
+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;
+
+    if (p_type != XML_READER_STARTELEM)
+        return -1;
+    if( p_node != "Asset")
+        return -1;
+    /* loop on Assets Node */
+    while( ( type = ReadNextNode( p_xmlReader, node ) ) > 0 ) {
+        switch (type) {
+            case XML_READER_STARTELEM:
+                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 ) )
+                        return -1;
+                    this->s_path = this->chunk_vec[0].getPath();
+                } else {
+                    asset_tag = ASSET_UNKNOWN;
+                    return -1;
+                }
+                break;
+            case XML_READER_TEXT:
+                s_value = node;
+                if (unlikely(node.empty()))
+                    return -1;
+                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");
+                        return -1;
+                    }
+                    /* TODO: verification of Chunklist */
+                    goto end;
+                }
+                switch (asset_tag) {
+                    case ASSET_ID:
+                        if( node != "Id" )
+                            return -1;
+                        this->s_id = s_value;
+                        break;
+                    case  ASSET_PACKING_LIST:
+                        if( node != "PackingList" )
+                            return -1;
+                        if ( s_value == "true" )
+                            this->b_is_packing_list = true;
+                        break;
+                    case ASSET_ANNOTATION_TEXT:
+                        if( node != "AnnotationText" )
+                            return -1;
+                        this->s_annotation = s_value;
+                        break;
+                    default:
+                        //msg_Err(this->p_demux,"Unknow end attribute %s",s_value.c_str());
+                        break;
+                }
+        }
+    }
+end:
+    return 0;
+}
+
+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 ) {
+        switch (type) {
+            case XML_READER_STARTELEM:
+                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;
+                    return -1;
+                }
+                break;
+            case XML_READER_TEXT:
+                s_value = node;
+                if (unlikely(node.empty()))
+                    return -1;
+                break;
+            case XML_READER_ENDELEM:
+                if (node == "Asset") {
+                    /* Reach end node of asset */
+                    if (this->s_hash.empty()) {
+                        msg_Err(this->p_demux,"Asset Hash tag invalid");
+                        return -1;
+                    }
+                    if (this->ui_size == 0) {
+                        msg_Err(this->p_demux,"Asset Size tag invalid");
+                        return -1;
+                    }
+                    if (this->s_type.empty()) {
+                        msg_Err(this->p_demux,"Asset Type tag invalid");
+                        return -1;
+                    }
+                    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:
+                        msg_Err(this->p_demux," Error parsing asset in PKL");
+                        break;
+                }
+                break;
+        }
+    }
+end:
+    return 0;
+}
+
+void Asset::Dump()
+{
+    msg_Dbg(this->p_demux,"Id              = %s", this->s_id.c_str());
+    msg_Dbg(this->p_demux,"Path            = %s", this->s_path.c_str());
+    msg_Dbg(this->p_demux,"Is PKL          = %s", this->b_is_packing_list ? "True" : "False");
+    msg_Dbg(this->p_demux,"Hash            = %s", this->s_hash.c_str());
+    msg_Dbg(this->p_demux,"Size            = %i", this->ui_size);
+    msg_Dbg(this->p_demux,"Type            = %s", this->s_type.c_str());
+    msg_Dbg(this->p_demux,"OrignalFileName = %s", this->s_original_filename.c_str());
+    msg_Dbg(this->p_demux,"AnnotationText  = %s", this->s_annotation.c_str());
+}
+
+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;
+
+    if (p_type != XML_READER_STARTELEM)
+        return -1;
+    if( p_node != "ChunkList" )
+        return -1;
+    /* loop on Assets Node */
+    while( ( type = ReadNextNode( p_xmlReader, node ) ) > 0 ) {
+         switch (type) {
+            case XML_READER_STARTELEM:
+                {
+                    Chunk chunk(this->p_demux);
+                    if (node != "Chunk" )
+                        return -1;
+                    if ( chunk.Parse(p_xmlReader, node, type) )
+                        return -1;
+                    chunk_vec.push_back(chunk);
+                    break;
+                }
+            case XML_READER_ENDELEM:
+                if ( node == p_node) {
+                    if (chunk_vec.size() != 1 ) {
+                        msg_Err(this->p_demux, "chunklist of size greater than one not supported");
+                        return -1;
+                        }
+                    this->chunk_vec = chunk_vec;
+                    goto end;
+                }
+                break;
+        }
+    }
+end:
+    return 0;
+}
+
+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)
+        return -1;
+    if( p_node != "AssetList" )
+        return -1;
+    /* loop on AssetList nodes */
+    while( ( type = ReadNextNode( p_xmlReader, node ) ) > 0 ) {
+        switch (type) {
+            case XML_READER_STARTELEM:
+                if (node != "Asset" )
+                    return -1;
+                asset = new Asset(this->p_demux);
+                if ( unlikely(asset == NULL) )
+                    return -1;
+                if (asset->Parse(p_xmlReader, node, type)){
+                    delete asset;
+                    return -1;
+                }
+                p_dcp->p_asset_list->push_back(asset);
+                break;
+
+            case XML_READER_ENDELEM:
+                if (node == "AssetList" )
+                    return 0;
+                break;
+            default:
+            case XML_READER_TEXT:
+                msg_Err(this->p_demux, "Error parsing AssetList in AssetMap");
+                return -1;
+        }
+    }
+    return -1;
+}
+
+Asset * AssetMap::getAssetById(AssetList *asset_list, const string p_id)
+{
+    AssetList::iterator index = asset_list->begin() ;
+    for (index = asset_list->begin(); index != asset_list->end(); ++index)
+        if ((*index)->getId() == p_id )
+            return *index;
+    return NULL;
+}
+
+/*
+ * XmlFile Class
+ */
+XmlFile::~XmlFile() {}
+
+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;
+}
+
+PKL::~PKL() {
+    vlc_delete_all(vec_cpl);
+}
+
+int PKL::Parse()
+{
+    string node;
+    int type;
+    string s_value;
+    PKLTag_t i_tag = PKL_UNKNOWN;
+    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 ) {
+        switch (type) {
+            case XML_READER_STARTELEM:
+                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()
+{
+    if ( this->vec_cpl.size() != 0 ) {
+        msg_Err(this->p_demux, "CPLs already checked");
+        return -1;
+    }
+
+    for (AssetList::iterator index = this->asset_list->begin();
+            index != this->asset_list->end(); ++index) {
+        Asset *asset = *index;
+        if ( asset->getType().find("text/xml") == string::npos) {
+            /* not an xml file */
+            continue;
+        }
+
+        CPL *cpl = new (nothrow) CPL(this->p_demux,
+                      this->s_dcp_path + asset->getPath(),
+                      this->asset_list);
+        if ( unlikely(cpl == NULL) )
+                    return -1;
+        if ( cpl->IsCPL() )
+            /* CPL Found */
+            this->vec_cpl.push_back(cpl);
+        else
+            delete cpl;
+    }
+    return this->vec_cpl.size();
+}
+
+
+int PKL::ParseAssetList(string p_node, int p_type) {
+    string node;
+    int type;
+
+    if (p_type != XML_READER_STARTELEM)
+        return -1;
+    if( p_node != "AssetList")
+        return -1;
+    while( ( type = ReadNextNode( this->p_xmlReader, node ) ) > 0 ) {
+        switch (type) {
+            case XML_READER_STARTELEM:
+                if( node =="Asset") {
+                    if ( this->ParseAsset(node, type) )
+                        return -1;
+                } else
+                    return -1;
+                break;
+            case XML_READER_ENDELEM:
+                if ( node == p_node) {
+                    /* parse of chunklist finished */
+                    goto end;
+                }
+                break;
+            }
+    }
+end:
+    return 0;
+}
+
+int PKL::ParseAsset(string p_node, int p_type) {
+    string node;
+    int type;
+    string s_value;
+    Asset *asset = NULL;
+
+    if (p_type != XML_READER_STARTELEM)
+        return -1;
+    if( p_node != "Asset")
+        return -1;
+
+    /* 1st node shall be Id" */
+    if (( type = ReadNextNode( this->p_xmlReader, node ) ) > 0)
+        if ( ! ((type == XML_READER_STARTELEM) && (node == "Id")))
+            return -1;
+    if (( type = ReadNextNode( this->p_xmlReader, node ) ) > 0)
+         if (type == XML_READER_TEXT) {
+            s_value = node;
+            if (unlikely(node.empty()))
+                return -1;
+            }
+    if (( type = ReadNextNode( this->p_xmlReader, node ) ) > 0)
+        if (type == XML_READER_ENDELEM) {
+            asset = AssetMap::getAssetById(this->asset_list, s_value);
+            if (asset  == NULL)
+                return -1;
+        }
+     if (asset == NULL)
+        return -1;
+     if ( asset->ParsePKL(this->p_xmlReader) )
+        return -1;
+    return 0;
+}
+
+int PKL::ParseSigner(string p_node, int p_type)
+{
+    string node;
+    int type;
+
+    if (p_type != XML_READER_STARTELEM)
+        return -1;
+    if( p_node != "Signer")
+        return -1;
+
+    while( ( type = ReadNextNode( this->p_xmlReader, node ) ) > 0 ) {
+        /* TODO not implemented. Just parse until end of Signer node */
+            if ((node == p_node) && (type = XML_READER_ENDELEM))
+                return 0;
+    }
+
+    msg_Err(this->p_demux, "Parse of Signer finished bad");
+    return -1;
+}
+
+int PKL::ParseSignature(string p_node, int p_type)
+{
+    string node;
+    int type;
+
+    if (p_type != XML_READER_STARTELEM)
+        return -1;
+    if( p_node != "ds:Signature")
+        return -1;
+
+    while (( type = ReadNextNode( this->p_xmlReader, node ) ) > 0 ) {
+        /* TODO not implemented. Just parse until end of Signature node */
+            if ((node == p_node) && (type = XML_READER_ENDELEM))
+                return 0;
+    }
+    msg_Err(this->p_demux, "Parse of Signature finished bad");
+    return -1;
+}
+
+/*
+ * Reel Class
+ */
+int Reel::Parse(string p_node, int p_type) {
+    string node;
+    int type;
+    string s_value;
+
+    if (p_type != XML_READER_STARTELEM)
+        return -1;
+    if( p_node != "Reel")
+        return -1;
+
+    while (( 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))
+                        return -1;
+                    this->s_id = s_value;
+                } else if ( node =="AssetList" ) {
+                    if (this->ParseAssetList(node, type))
+                        return -1;
+                } else {
+                    /* unknown tag */
+                    msg_Err(this->p_demux, "Reel::Parse, unknown tag:%s", node.c_str());
+                    return -1;
+                }
+                break;
+            case XML_READER_TEXT:
+                /* Error */
+                msg_Err(this->p_demux, "Reel parsing error");
+                return -1;
+            case XML_READER_ENDELEM:
+                /* verify correctness of end node */
+                if ( node == p_node) {
+                    /* TODO : verify Reel id */
+                    return 0;
+                }
+        }
+    }
+    return -1;
+}
+
+
+Asset * Reel::getTrack(TrackType_t e_track)
+{
+    switch (e_track) {
+        case TRACK_PICTURE:
+            return this->p_picture_track;
+        case TRACK_SOUND:
+            return this->p_sound_track;
+        case TRACK_SUBTITLE:
+            return this->p_subtitle_track;
+        case TRACK_UNKNOWN:
+        default:
+            break;
+    }
+    return NULL;
+}
+
+int Reel::ParseAssetList(string p_node, int p_type) {
+    string node;
+    int type;
+    string s_value;
+
+    if (p_type != XML_READER_STARTELEM)
+        return -1;
+    if( p_node != "AssetList")
+        return -1;
+
+    while (( type = ReadNextNode( this->p_xmlReader, node ) ) > 0 )  {
+        switch (type) {
+            case XML_READER_STARTELEM:
+                if (node =="MainPicture") {
+                    if ( this->ParseAsset(node, type, TRACK_PICTURE) )
+                        return -1;
+                } else if (node =="MainSound") {
+                    if ( this->ParseAsset(node, type, TRACK_SOUND) )
+                        return -1;
+                } else if (node =="MainSubtitle") {
+                    if ( this->ParseAsset(node, type, TRACK_SUBTITLE) )
+                        return -1;
+                } else {
+                    /* unknown tag */
+                    msg_Err(this->p_demux, "Reel::Parse, unknown tag:%s", node.c_str());
+                    return -1;
+                }
+                break;
+            case XML_READER_TEXT:
+                /* Parsing error */
+                msg_Err(this->p_demux, "AssetList parsing error");
+                return -1;
+            case XML_READER_ENDELEM:
+                /* verify correctness of end node */
+                if ( node == p_node) {
+                    /* TODO : verify id */
+                    return 0;
+                }
+        }
+    }
+    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)
+        return -1;
+
+    /* 1st node shall be Id */
+    if (( type = ReadNextNode( this->p_xmlReader, node ) ) > 0)
+        if ( ! ((type == XML_READER_STARTELEM) && (node == "Id")))
+            return -1;
+
+    if ( ReadEndNode(this->p_xmlReader, node, type, s_value) )
+        return -1;
+
+    asset = AssetMap::getAssetById(this->p_asset_list, s_value);
+    if (asset  == NULL)
+        return -1;
+
+    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))
+                        return -1;
+                } else if (node == "IntrinsicDuration") {
+                    if ( ReadEndNode(this->p_xmlReader, node, type, s_value))
+                        return -1;
+                        asset->setIntrinsicDuration(atoi(s_value.c_str()));
+                } else if (node == "EntryPoint") {
+                    if ( ReadEndNode(this->p_xmlReader, node, type, s_value))
+                        return -1;
+                        asset->setEntryPoint(atoi(s_value.c_str()));
+                } else if (node == "Duration") {
+                    if ( ReadEndNode(this->p_xmlReader, node, type, s_value))
+                        return -1;
+                        asset->setDuration(atoi(s_value.c_str()));
+                } else if (node == "KeyId") {
+                    if ( ReadEndNode(this->p_xmlReader, node, type, s_value))
+                        return -1;
+                } else if (node == "Hash") {
+                    if ( ReadEndNode(this->p_xmlReader, node, type, s_value))
+                        return -1;
+                } else if (node == "FrameRate") {
+                    if ( ReadEndNode(this->p_xmlReader, node, type, s_value))
+                        return -1;
+                } else if (node == "ScreenAspectRatio") {
+                    if ( ReadEndNode(this->p_xmlReader, node, type, s_value))
+                        return -1;
+                } else if (node == "Language") {
+                    if ( ReadEndNode(this->p_xmlReader, node, type, s_value))
+                        return -1;
+                } else {
+                    /* unknown tag */
+                    msg_Err(this->p_demux, "Reel::Parse, unknown tag:%s", node.c_str());
+                    return -1;
+                }
+                break;
+            case XML_READER_TEXT:
+                /* impossible */
+                return -1;
+                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;
+}
+
+/*
+ * 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();
+};
+
+CPL::~CPL() {
+    vlc_delete_all(vec_reel);
+}
+
+int CPL::Parse()
+{
+    string node;
+    int type;
+    string s_value;
+    CPLTag_t i_tag = CPL_UNKNOWN;
+    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 ) {
+        switch (type) {
+            case XML_READER_STARTELEM:
+                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;
+
+    if (p_type != XML_READER_STARTELEM)
+        return -1;
+    if( p_node != "ReelList")
+        return -1;
+    while( ( type = ReadNextNode( this->p_xmlReader, node ) ) > 0 ) {
+        switch (type) {
+            case XML_READER_STARTELEM: {
+                Reel *p_reel = new (nothrow) Reel( this->p_demux, this->asset_list, this->p_xmlReader);
+                if ( unlikely(p_reel == NULL) )
+                    return -1;
+                if( node =="Reel") {
+                    if ( p_reel->Parse(node, type) ) {
+                        delete p_reel;
+                        return -1;
+                    }
+                } else {
+                    delete p_reel;
+                    return -1;
+                }
+                this->vec_reel.push_back(p_reel);
+
+                break;
+            }
+            case XML_READER_TEXT:
+                /* impossible */
+                break;
+            case XML_READER_ENDELEM:
+                if ( node == p_node)
+                    return 0;
+                break;
+            }
+    }
+    return -1;
+}
+
+
+int CPL::DummyParse(string p_node, int p_type)
+{
+    string node;
+    int type;
+
+    if (p_type != XML_READER_STARTELEM)
+        return -1;
+
+    if (xml_ReaderIsEmptyElement( this->p_xmlReader))
+        return 0;
+
+    while (( 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))
+            return 0;
+    }
+
+    return -1;
+}
diff --git a/modules/access/dcp/dcpparser.h b/modules/access/dcp/dcpparser.h
new file mode 100644
index 0000000..0e101c5
--- /dev/null
+++ b/modules/access/dcp/dcpparser.h
@@ -0,0 +1,293 @@
+/*****************************************************************************
+ * Copyright (C) 2013 VLC authors and VideoLAN
+ *
+ * Authors: Nicolas Bertrand <nico at isf.cc>
+ *          Jean-Baptiste Kempf <jb at videolan.org>
+ *
+ * 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 Asset;
+class AssetList: public std::list<Asset *> {};
+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;               /* Picture file name */
+    string audiofile;               /* Sound file name */
+
+    int i_video_entry;              /* Picture entry point */
+    int i_audio_entry;              /* Sound entry point */
+
+
+    ~dcp_t( ) {
+        vlc_delete_all(pkls);
+        vlc_delete_all(*p_asset_list);
+        delete(p_asset_list);
+    }
+};
+
+
+class XmlFile
+{
+public:
+    XmlFile( demux_t * p_demux, string s_path):
+    p_demux(p_demux), s_path(s_path),
+    p_stream(NULL),
+    p_xml(NULL),
+    p_xmlReader(NULL),
+    type(XML_UNKNOWN) {}
+
+    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(demux_t * demux):
+        i_vol_index(1), i_offset(0), i_length(0),
+        p_demux(demux) {};
+    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;
+    demux_t      *p_demux;
+};
+
+class Asset {
+public:
+    /* Constructor */
+    Asset (demux_t * demux):
+        b_is_packing_list(false),  ui_size(0),
+        i_intrisic_duration(0), i_entry_point(0), i_duration(0),
+        p_demux(demux) {}
+    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; };
+    void setEntryPoint(int i_val) { this->i_entry_point = i_val; };
+    void setDuration (int i_val) { this->i_duration = i_val; };
+    void setIntrinsicDuration (int i_val) { this->i_intrisic_duration = i_val; };
+    string getId() const { return this->s_id; } ;
+    string getPath() const { return this->s_path; };
+    string getType() const { return this->s_type; };
+    int getEntryPoint() const { return this->i_entry_point; };
+    int getDuration() const { return this->i_duration; };
+    int getIntrinsicDuration() const { return this->i_intrisic_duration; };
+
+    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 Reel
+{
+public:
+    Reel(demux_t * demux, AssetList *asset_list, xml_reader_t *xmlReader)
+        : p_asset_list(asset_list), p_xmlReader(xmlReader), p_demux(demux)
+         {};
+    int Parse(string p_node, int p_type);
+    Asset * getTrack(TrackType_t e_track);
+
+private:
+    AssetList *p_asset_list;
+    xml_reader_t *p_xmlReader;
+    demux_t      *p_demux;
+
+    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*);
+    ~CPL();
+    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);
+    ~PKL();
+    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) {};
+    ~AssetMap();
+
+    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




More information about the vlc-devel mailing list