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

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


Hi,

I don't have the time to review the xml code now but here are some
remarks.
Part two tonight.

Le vendredi 22 novembre 2013 à 07:29:46, Nicolas Bertrand a écrit :
> [...]
> +    demux_sys_t():
> +        p_PicMXFReader( NULL ),
> +        p_PicDesc( NULL ),
> +        p_AudioMXFReader( NULL ),
> +        p_AudioDesc( NULL ),
> +        p_out( NULL ),
> +        p_video_es( NULL ),
> +        p_audio_es( NULL ),
> +        p_dcp( NULL ),
> +        frame_no( 0 )
> +    {
> +        PictureEssType = ESS_UNKNOWN;
Why not PictureEssType( ESS_UNKNOWN )?
> +    }
> +
> +/*****************************************************************************
> + * 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;
> +    vlc_fourcc_t fcc;
> +    int retval;
> +    JP2K::MXFReader         *p_PicMXFReader;
> +    JP2K::MXFSReader        *p_PicMXFSReader;
> +    JP2K::PictureDescriptor *p_PicDesc;
> +    MPEG2::MXFReader        *p_VideoMXFReader;
> +    MPEG2::VideoDescriptor  *p_VideoDesc;
> +    PCM::MXFReader          *p_AudioMXFReader;
> +    PCM::AudioDescriptor    *p_AudioDesc;
Declare them when you need them, especially temp variables like that. 
> +
> +    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;
> +        }
Inconsistent indentation.
> +    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:
> +            fcc = VLC_CODEC_JPEG2000;
> +            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 */
> +                p_PicMXFSReader = p_sys->p_PicMXFSReader = new ( nothrow ) JP2K::MXFSReader();
> +
> +                if( !p_PicMXFSReader) {
> +                    retval = VLC_ENOMEM;
> +                    goto error;
> +                    }
Indentation.
> +                if( !ASDCP_SUCCESS( p_PicMXFSReader->OpenRead( p_sys->p_dcp->videofile.c_str() ) ) ) {
I suppose that there is no way to give the asdcplip some callbacks for
open/read/seek/close?

> +                    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 );
> +                p_sys->p_PicMXFSReader = p_PicMXFSReader;
> +            } else {                                            /* 2D JPEG2000 */
> +                p_PicMXFReader = p_sys->p_PicMXFReader = new ( nothrow ) JP2K::MXFReader();
> +                if( !p_PicMXFReader ) {
> +                    retval = VLC_ENOMEM;
> +                    goto error;
> +                    }
Indentation.
> +                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 );
> +                p_sys->p_PicMXFReader = p_PicMXFReader;
Already done previously.
> +            }
> +            es_format_Init( &video_format, VIDEO_ES, fcc );
Is fcc really useful?
> +            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;
This feels quite redundant if you already hold them in p_sys->p_PicDesc.
Of course one could argue that you avoid one dereference but still. Is
it that critical? Or is it just because there could be a p_VideoDesc
instead. In that case, is it really useful to keep p_PicDesc in the
p_sys?
> +            break;
> +        case ESS_MPEG2_VES:
> +            fcc = VLC_CODEC_MPGV;
> +            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, 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_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 );
> +    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() );
> +            retval = VLC_EGENERIC;
> +            goto error;
> +        case ESS_PCM_24b_48k:
> +        case ESS_PCM_24b_96k:
> +            fcc = VLC_CODEC_S24L;
> +            break;
> +        default:
> +            msg_Err( p_demux, "Unrecognized audio format" );
> +            retval = VLC_EGENERIC;
> +            goto error;
> +    }
> +
> +    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, fcc );
> +    if( p_AudioDesc->AudioSamplingRate.Denominator != 0 )
> +        audio_format.audio.i_rate = p_AudioDesc->AudioSamplingRate.Numerator / p_AudioDesc->AudioSamplingRate.Denominator;
Shouldn't there be a more definitive error if the rate is wrong? You are
dealing with raw audio. At least use a "standard" value like 48000
rather than garbage value from your memory 
> +    audio_format.audio.i_bitspersample = p_AudioDesc->QuantizationBits;
> +    audio_format.audio.i_blockalign = p_AudioDesc->BlockAlign;
> +    audio_format.audio.i_channels = p_AudioDesc->ChannelCount;
Beware of channel mapping. If you have more than 2 channels, the core
will expect the samples in a precise order. Expect bad mapping issues.
> +
> +    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" );
> +        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;
> +    mtime_t pts = 0;
> +    uint32_t i_audio_buffer = PCM::CalcFrameBufferSize(*p_sys->p_AudioDesc);
> +    JP2K::FrameBuffer  PicFrameBuff(FRAME_BUFFER_SIZE);
> +    MPEG2::FrameBuffer VideoFrameBuff(FRAME_BUFFER_SIZE);
I hope that this doesn't allocate FRAME_BUFFER_SIZE bytes else there is
something fishy. So better declare them when you need them.

> +    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:
> +            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, JP2K::SP_LEFT, PicFrameBuff, 0, 0)) ) {
> +                    PicFrameBuff.SetData(0,0);
> +                    goto error_asdcp;
> +                }
> +             } else {
> +                if ( ! ASDCP_SUCCESS(
> +                        p_sys->p_PicMXFReader->ReadFrame(i, PicFrameBuff, 0, 0)) ) {
> +                    PicFrameBuff.SetData(0,0);
> +                    goto error_asdcp;
> +                }
> +            }
> +            p_video_frame->i_buffer = PicFrameBuff.Size();
> +            break;
> +
> +        case ESS_MPEG2_VES:
> +            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, 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 = 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;
CLOCK_FREQ may be more flexible and explicit than just "1000000"
> +
> +    /* audio frame */
> +    if ( ( p_audio_frame = block_Alloc( i_audio_buffer )) == NULL ) {
> +        goto error;
> +        }
Indentation.
> +    if ( ! ASDCP_SUCCESS(
> +            AudioFrameBuff.SetData(p_audio_frame->p_buffer, i_audio_buffer)) ) {
> +        goto error_asdcp;
> +        }
Indentation.
> +
> +    if ( ! ASDCP_SUCCESS(
> +            p_sys->p_AudioMXFReader->ReadFrame(i, AudioFrameBuff, 0, 0)) ) {
> +        AudioFrameBuff.SetData(0,0);
> +        goto error_asdcp;
> +    }
> +
> +    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;
> +
> +    pts = __MIN(p_video_frame->i_pts, p_audio_frame->i_pts);
> +
> +    es_out_Control( p_demux->out, ES_OUT_SET_PCR, pts );
Make sure that pcr is strictly increasing or expect RESET and flushes of
the decoders' queue
> +    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");
> +    if (p_video_frame)
> +        block_Release(p_video_frame);
> +    if (p_audio_frame)
> +        block_Release(p_audio_frame);
> +    return -1;
If both do the same thing just do:
error_asdcp:
    msg_Err( p_demux, "Couldn't read frame with ASDCP");
error:
    if (p_video_frame)
    [...]
    return -1;
> +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 ) * 1000000 );
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;
Unless I've missed it p_sys->i_pts isn't set in Demux().
> +            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 / ( 1000000 * p_sys->frame_rate_denom );
> +            p_sys->i_pts= i64;
> +            es_out_Control( p_demux->out, ES_OUT_SET_NEXT_DISPLAY_TIME, ( mtime_t ) i64 );
Beware of use of ES_OUT_SET_NEXT_DISPLAY_TIME without a proper SET_PCR
before. You could be stuck for a long time.
> +            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 check if a file name ends with a given suffix
> + * @param str File name
> + * @param suffix Suffix to look for
> + * @return true if the file name ends with the given suffix, false otherwise
> + */
> +bool endsWith( const char * str, const char * suffix )
> +{
> +    bool b_end_with_suffix = false;
> +    size_t lenstr , lensuffix;
> +
> +    if( !str || !suffix )
> +        return b_end_with_suffix;
> +
> +    lenstr    = strlen( str );
> +    lensuffix = strlen( suffix );
> +    b_end_with_suffix = ( ( lensuffix <= lenstr ) &&
> +                        ( !strncasecmp(str + lenstr - lensuffix, suffix, lensuffix) ) );
> +    return b_end_with_suffix;
> +}
> +
> +
> +/**
> + * 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 */
> +    std::cout << " Enter CloseDcpAndMxf "<< std::endl;
> +    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();

Lack of es_out_Del()
> +
> +    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;
> +    /* We check if there is a "/" at the end of the path */
> +    if( !endsWith( p_demux->psz_file, "/" ) )
If your goal is just to check the presence of a single character,
endsWith is completely overkill.
> +    {
> +        try
> +        {
> +            p_dcp->path.append( "/" );
> +        }
> +        catch(...)
> +        {
> +            msg_Err( p_demux, "String handling failed" );
> +            retval = VLC_EGENERIC;
> +            goto error;
> +        }
> +    }
> +
> +    /* Parsing XML files to get audio and video files */
> +    msg_Dbg( p_demux, "parsing XML files..." );
> +    if( ( retval = parseXML( p_demux ) ) )
> +        goto error;
> +
> +    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, "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;
> +
> +error :
> +    return retval;
> +}
> +
> +
> +/*****************************************************************************
> + * functions for XML parsing
> + *****************************************************************************/
> +
> +/**
> + * Function to retrieve the path to the ASSETMAP file.
> + * @param p_demux DCP access_demux.
> + */
> +static const char * assetmapPath( demux_t * p_demux )
> +{
> +    DIR *dir = NULL;
> +    struct dirent *ent = NULL;
> +    string result;
> +
> +    if( ( dir = opendir ( p_demux->psz_file ) ) != NULL )
Does this work on windows?
> +    {
> +        /* 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" );
> +                    closedir( dir );
> +                    return NULL;
> +                }
> +                break;
> +            }
> +        }
> +        closedir( dir );
> +    }
> +    else
> +    {
> +        msg_Err( p_demux, "Could not open the directory: %s", p_demux->psz_file );
> +        return NULL;
> +    }
> +
> +    /* if no assetmap file */
> +    if( result.empty() )
> +    {
> +        msg_Err( p_demux, "No ASSETMAP found in the directory: %s", p_demux->psz_file );
> +        return NULL;
> +    }
> +
> +    return result.c_str();
> +}
> +
> +
> +/**
> + * 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;
> +
> +    const char *assetmap_path = assetmapPath( p_demux );
> +    /* We get the ASSETMAP file path */
> +    if( assetmap_path == NULL )
> +        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;
> +
> +    return VLC_SUCCESS; /* TODO : perform checking on XML parsing */
> +}

Regards,

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



More information about the vlc-devel mailing list