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

Jean-Baptiste Kempf jb at videolan.org
Tue Sep 3 00:57:33 CEST 2013


On 02 Sep, Nicolas Bertrand wrote :
> +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"])

Oh god, no .pc?

> +    set_description( N_( "Digital Cinema Package access-demux module" ) )

I don't think you should put "access-demux" in there.

> +    file_t *files[20];       /*!< Files defined in ASSETMAP : we assume that there are less than 20 files */

make the 20 a define and reuse it in the code.

> +int dcpInit ( demux_t *p_demux );
> +int parserXML ( demux_t * p_demux );

Poor name. Call it parseXML.

> +void freeMem( demux_t *p_demux );

Poor name. Too generic.

> +    /***************************************************
> +     ***************** open video file *****************
> +     ***************************************************/

************************************************************
************************************************************
************************ Seriously? ************************
************************************************************
************************************************************
************************************************************

:)

> +    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 )
> +            {
> +                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 )
> +            {
> +                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 )
> +            {
> +                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->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);
> +        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 )
> +    {
> +        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;
> +}


You should factor the error path.
And I think you can accept files where one track fails, no?


> +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 0;
> +
> +    /* 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 -1;
> +            }
> +
> +            if( ( p_video_frame = block_Alloc( PicFrameBuff.Size() ) ) != NULL )
> +                memcpy( p_video_frame->p_buffer, PicFrameBuff.Data(), PicFrameBuff.Size() );
> +            else
> +                return -1;
> +
> +            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 -1;
> +            }
> +
> +            if( ( p_video_frame = block_Alloc( PicFrameBuff.Size() ) ) != NULL )
> +                memcpy( p_video_frame->p_buffer, PicFrameBuff.Data(), PicFrameBuff.Size() );
> +            else
> +                return -1;
> +
> +            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 -1;
> +            }
> +
> +            if( ( p_video_frame = block_Alloc( VideoFrameBuff.Size() ) ) != NULL )
> +                memcpy( p_video_frame->p_buffer, VideoFrameBuff.Data(), VideoFrameBuff.Size() );
> +            else
> +                return -1;
> +
> +            p_video_frame->i_buffer = VideoFrameBuff.Size();
> +            break;
> +        }
> +        default:
> +            msg_Err( p_demux, "Unrecognized video format" );
> +            return -1;
> +    }
> +
> +    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;
> +
> +    /* 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 -1;
> +    }
> +
> +    if( ( p_audio_frame = block_Alloc( AudioFrameBuff.Size() ) ) != NULL )
> +        memcpy( p_audio_frame->p_buffer, AudioFrameBuff.Data(), AudioFrameBuff.Size() );
> +    else
> +        return -1;
> +
> +    p_audio_frame->i_buffer = AudioFrameBuff.Size();
> +    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;
> +
> +    if( p_video_frame->i_pts < p_audio_frame->i_pts )
> +        pts = p_video_frame->i_pts;
> +    else
> +        pts = p_audio_frame->i_pts;
> +    p_sys->i_pts = 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;
> +}

Same as above for the error path.

> +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;
> +}

This is not very beautiful, tbh.

> +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;
> +}

I don't really get the retval use, but OK.

> +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;
> +    }

Add a line here.

> +    /* 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) 

Wrap comment, seriously.

> +     * 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;
> +}


> +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 ] )
> +                    {
> +                        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;
> +                    }
> +                }
> +            }
> +        }


Please reduce the nesting levels. This is getting crazy.


> +        /* 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;
> +                    }
> +                }
> +            }
> +        }
> +    }

Idem.



-- 
Jean-Baptiste Kempf
http://www.jbkempf.com/ - +33 672 704 734
Sent from my Electronic Device



More information about the vlc-devel mailing list