[vlc-devel] [PATCH] DCP: allow to read subtitles
Denis Charmet
typx at dinauz.org
Mon Mar 3 18:13:42 CET 2014
Hi,
Le samedi 01 mars 2014 à 05:20:12, Valentin Vetter a écrit :
> +typedef struct
> +{
> + int64_t i_start;
> + int64_t i_stop;
> +
> + char *psz_text;
> +} subtitle_t;
why not use block_t?
> +
> +typedef struct
> +{
> + xml_t *xml;
> + xml_reader_t *xml_reader;
> + int count;
> +} sub_xml_t;
> +
> +struct demux_sub_sys_t
> +{
> + int i_type;
> + sub_xml_t sub_xml;
> + es_out_id_t *es;
> +
> + int64_t i_next_demux_date;
> + int64_t i_microsecperframe;
> +
> + char *psz_header;
> + int i_subtitle;
> + int i_subtitles;
> + subtitle_t *subtitle;
I assume those will be allocated shouldn't you have a destructor?
> +
> + int64_t i_length;
> +
> + struct
> + {
> + bool b_inited;
> +
> + int i_comment;
> + int i_time_resolution;
> + int i_time_shift;
> + } jss;
> + struct
> + {
> + bool b_inited;
> +
> + float f_total;
> + float f_factor;
> + } mpsub;
> +};
> +
> class demux_sys_t
> {
> public:
> @@ -127,12 +182,20 @@ class demux_sys_t
> /* ASDCP Audio MXF Reader */
> vector<audioReader_t> v_audioReader;
>
> + /* Subtitles information */
> + vector<demux_sub_sys_t*> v_sub_sys;
> +
> /* audio buffer size */
> uint32_t i_audio_buffer;
>
> /* elementary streams */
> es_out_id_t *p_video_es;
> es_out_id_t *p_audio_es;
> + es_out_id_t *p_sub_es;
isn't that somehow redundant with es inside demux_sub_sys_t?
> +
> + /* subtitle parser */
> + stream_t *p_subtitle_parser;
> + stream_t *p_subtitle_stream;
>
> /* DCP object */
> dcp_t *p_dcp;
> @@ -153,6 +216,9 @@ class demux_sys_t
> /* current audio reel */
> unsigned int i_audio_reel;
>
> + /* current subtitle reel */
> + unsigned int i_sub_reel;
> +
> uint8_t i_chans_to_reorder; /* do we need channel reordering */
> uint8_t pi_chan_table[AOUT_CHAN_MAX];
> uint8_t i_channels;
> @@ -163,13 +229,16 @@ class demux_sys_t
> PictureEssType ( ESS_UNKNOWN ),
> v_videoReader(),
> v_audioReader(),
> + v_sub_sys(),
> p_video_es( NULL ),
> p_audio_es( NULL ),
> + p_sub_es( NULL ),
> p_dcp( NULL ),
> frame_no( 0 ),
> frames_total( 0 ),
> i_video_reel( 0 ),
> - i_audio_reel( 0 ) {};
> + i_audio_reel( 0 ),
> + i_sub_reel( 0 ) {};
>
> ~demux_sys_t()
> {
> @@ -281,6 +350,9 @@ static int Demux( demux_t * );
> static int Control( demux_t *, int, va_list );
>
> int dcpInit ( demux_t *p_demux );
> +int OpenSubtitle( demux_t *p_demux, const char *filePath, int );
> +int SubtitleDemux( demux_t *, int );
> +static int ParseDCSubtitle ( demux_t *, subtitle_t *, int, int );
> int parseXML ( demux_t * p_demux );
> static inline void fillVideoFmt(
> video_format_t * fmt, unsigned int width, unsigned int height,
> @@ -411,7 +483,6 @@ static int Open( vlc_object_t *obj )
> break;
> }
> case ESS_MPEG2_VES: {
> -
> MPEG2::MXFReader *p_VideoMXFReader = new ( nothrow ) MPEG2::MXFReader();
>
> videoReader_t videoReader;
> @@ -533,7 +604,6 @@ static int Open( vlc_object_t *obj )
> audioReader_t audioReader;
> audioReader.p_AudioMXFReader = p_AudioMXFReader;
> p_sys->v_audioReader.push_back( audioReader );
> -
> }
> es_format_Init( &audio_format, AUDIO_ES, VLC_CODEC_S24L );
> if( AudioDesc.AudioSamplingRate.Denominator != 0 )
> @@ -573,9 +643,33 @@ static int Open( vlc_object_t *obj )
> retval = VLC_EGENERIC;
> goto error;
> }
> +
> + /* Open subtitle file */
> + if( p_sys->p_dcp->sub_reels.size() > 0 )
> + {
> + for ( uint8_t i = 0; i < ( p_sys->p_dcp->sub_reels.size() ); i++)
> + {
> + if ( retval = OpenSubtitle( p_demux, p_sys->p_dcp->sub_reels[i].filename.c_str(), i ) )
> + return retval;
leak
> + }
> + }
> +
> + es_format_t fmt;
> + es_format_Init( &fmt, SPU_ES, VLC_CODEC_SUBT );
> + fmt.subs.psz_encoding = strdup( "UTF-8" );
> +
> + if( ( p_demux->p_sys->p_sub_es = es_out_Add( p_demux->out, &fmt ) ) == NULL )
> + {
> + msg_Err( p_demux, "Failed to add subtitle es" );
If you don't use a program in the format, the only reason for it to fail
is a lack of memory so avoid traces.
> + free( p_sys );
> + return VLC_EGENERIC;
> + }
> +
> + es_out_Control( p_demux->out, ES_OUT_SET_ES_DEFAULT, p_demux->p_sys->p_sub_es );
> + es_format_Clean( &fmt );
I think that you can just free(fmt.subs.psz_encoding) instead of that.
> +
> p_demux->pf_demux = Demux;
> p_demux->pf_control = Control;
> - p_sys->frame_no = p_sys->p_dcp->video_reels[0].i_entrypoint;
>
> return VLC_SUCCESS;
> error:
> @@ -631,6 +725,21 @@ static int Demux( demux_t *p_demux )
> }
> }
>
> + /* swaping subtitle reels */
> + if ( p_sys->frame_no == p_sys->p_dcp->sub_reels[p_sys->i_sub_reel].i_absolute_end )
> + {
> + if ( p_sys->i_sub_reel + 1 == p_sys->p_dcp->sub_reels.size() )
> + {
> + return 0;
This will cause an end of file, do you really want that?
> + }
> + else
> + {
> + p_sys->i_sub_reel++;
> + es_out_Control( p_demux->out, ES_OUT_SET_ES_DEFAULT, p_demux->p_sys->p_sub_es );
> + }
> + }
> +
> +
> /* video frame */
> switch( p_sys->PictureEssType )
> {
> @@ -719,6 +828,9 @@ static int Demux( demux_t *p_demux )
> 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 );
>
> + if ( p_sys->v_sub_sys[p_sys->i_sub_reel] )
> + SubtitleDemux( p_demux, p_sys->i_sub_reel );
> +
> p_sys->frame_no++;
>
> return 1;
> @@ -743,6 +855,9 @@ static int Control( demux_t *p_demux, int query, va_list args )
> int64_t *pi64, i64;
> demux_sys_t *p_sys = p_demux->p_sys;
>
> + int i_reel = 0;
> + bool b_correct_reel = false;
> +
Why declare it if you don't use it?
> switch ( query )
> {
> case DEMUX_CAN_PAUSE:
> @@ -970,3 +1085,241 @@ int parseXML ( demux_t * p_demux )
> delete assetmap;
> return VLC_SUCCESS; /* TODO : perform checking on XML parsing */
> }
> +
> +
> +/*****************************************************************************
> + * functions for subtitles
> + *****************************************************************************/
> +
> +static int XmlLoad( demux_t * p_demux, stream_t *s, int sub_nb )
> +{
> + demux_sub_sys_t *p_sys = p_demux->p_sys->v_sub_sys[sub_nb];
> + sub_xml_t *p_sub_xml = &p_sys->sub_xml;
> + xml_t *p_xml;
> + xml_reader_t *p_xml_reader;
> +
> + /* Create XML parser */
> + p_xml = xml_Create( p_demux );
> + if( ! p_xml )
> + return VLC_EGENERIC;
> +
> + /* Initialize XML reader */
> + p_xml_reader = xml_ReaderCreate( p_xml, s );
> + if( ! p_xml_reader )
> + return VLC_EGENERIC;
leak p_xml
> + p_sub_xml->xml = p_xml;
> + p_sub_xml->xml_reader = p_xml_reader;
> + return VLC_SUCCESS;
> +
> +}
> +
> +static void XmlUnLoad ( demux_t *p_demux, int sub_nb )
> +{
> + demux_sub_sys_t *p_sys = p_demux->p_sys->v_sub_sys[sub_nb];
> + sub_xml_t *p_sub_xml = &p_sys->sub_xml;
> + xml_ReaderDelete( p_sub_xml->xml_reader );
> + xml_Delete( p_sub_xml->xml );
> +
> +}
> +
> +static int ParseDCSubtitle( demux_t *p_demux, subtitle_t *p_subtitle, int i_idx, int sub_nb )
> +{
> + demux_sub_sys_t *p_sys = p_demux->p_sys->v_sub_sys[sub_nb];
> + sub_xml_t *p_sub_xml = &p_sys->sub_xml;
> + xml_reader_t * p_xml_reader = p_sub_xml->xml_reader;
> + const char *node = NULL;
> + int type = 0;
> + bool b_subtitle_tag = false;
> + bool b_quit = false;
> + char *psz_text = NULL;
> + int i_len = 0;
> + while( ( b_quit == false ) && ( type = xml_ReaderNextNode( p_xml_reader, &node ) ) > 0 )
> + {
> + switch (type)
> + {
> + case XML_READER_STARTELEM:
> + if( strcmp( node, "Subtitle" ) == 0 ) {
> + const char *val, *attr;
> + int h1, m1, s1, d1;
> + b_subtitle_tag = true;
> + i_len = 0;
> + while( ( attr = xml_ReaderNextAttr( p_xml_reader, &val ) ) ) {
> + if( ( strcmp( attr, "TimeIn" ) == 0 ) ) {
> + if( sscanf( val, "%d:%d:%d:%d", &h1, &m1, &s1, &d1 ) ==4 ) {
> + p_subtitle->i_start = ( (int64_t)h1 * 3600*1000 +
> + (int64_t)m1 * 60*1000 +
> + (int64_t)s1 * 1000 +
> + (int64_t)d1 ) * 1000;
> + }
> + }
> + if( ( strcmp(attr, "TimeOut" ) == 0 ) ) {
> + if( sscanf(val, "%d:%d:%d:%d", &h1, &m1, &s1, &d1) ==4 ) {
> + p_subtitle->i_stop = ( (int64_t)h1 * 3600*1000 +
> + (int64_t)m1 * 60*1000 +
> + (int64_t)s1 * 1000 +
> + (int64_t)d1 ) * 1000;
> + }
> + }
Beware if your sscanf fail for some reason you'll have garbage i_start,
i_stop
> + }
> + }
> + break;
> +
> + case XML_READER_TEXT:
> + if( b_subtitle_tag ) {
> + if( i_len == 0 ) {
> + psz_text = strdup(node);
> + i_len = strlen(psz_text);
> + } else {
> + int i_old = i_len;
> + i_len = strlen(node);
> + psz_text = (char *) realloc_or_free( psz_text, i_old + i_len + 1 + 1 );
> + strcat( psz_text, "\n" );
crash if realloc_or_free freed the data.
> + strcat( psz_text, node );
> + i_len = strlen(psz_text);
why not using i_old + i_len + 1?
> + }
> + }
> + break;
> +
> + case XML_READER_ENDELEM:
> + if( strcmp( node, "Subtitle" ) == 0 ) {
> + p_subtitle->psz_text = psz_text;
> + b_subtitle_tag = false ;
> + b_quit = true;
> + }
else
> + if( strcmp(node, "DCSubtitle") == 0 ) {
> + if( psz_text ) free(psz_text);
> + return VLC_EGENERIC;
> + }
> + break;
> +
> + default:
> + break;
> + }
> + }
> +
> + return VLC_SUCCESS;
> +}
> +
> +int OpenSubtitle( demux_t *p_demux, const char *filePath, int sub_nb )
> +{
> + demux_sub_sys_t *p_sys ;
> + const char * s_url = vlc_path2uri( filePath, "file" );
> + stream_t *p_stream;
> + int ret;
> + int i_max;
> +
> + /*TODO: Where put the free */
> + p_sys = new demux_sub_sys_t();
no check
> + p_demux->p_sys->v_sub_sys.push_back( p_sys );
> + p_demux->p_sys->v_sub_sys[sub_nb] = p_sys = (demux_sub_sys_t *) malloc( sizeof( *p_sys ) );
Uh?? smells like memleak.
> +
> + if( p_sys == NULL )
> + return VLC_ENOMEM;
> +
> + p_sys->psz_header = NULL;
> + p_sys->i_subtitle = 0;
> + p_sys->i_subtitles = 0;
> + p_sys->subtitle = NULL;
> + p_sys->i_microsecperframe = 40000;
> +
> + p_sys->jss.b_inited = false;
> + p_sys->mpsub.b_inited = false;
> +
> + /* HARD fix fps to 24 fps */
> + p_sys->i_microsecperframe = (int64_t)(1000000 / 24 );
> +
> + p_sys->i_type = SUB_TYPE_DCSUBTITLE;
Shouldn't all that belong to a constructor?
> +
> + /* Load the whole file */
> + p_stream = stream_UrlNew( p_demux, s_url );
> + if( ! p_stream )
> + return VLC_EGENERIC;
> + if ( ret = XmlLoad( p_demux, p_stream, sub_nb ) ) {
> + msg_Warn( p_demux, "Failure on loading XML subfile" );
> + free( p_sys );
here you free p_sys but not before isn't it dangerous with it already in
the vector?
> + stream_Delete( p_stream );
> + return ret;
> + }
> +
> + /* Parse it */
> + for( i_max = 0; ; )
> + {
> + if( p_sys->i_subtitles >= i_max )
> + {
> + i_max += 500;
> + if( !( p_sys->subtitle = (subtitle_t *)realloc_or_free( p_sys->subtitle,
> + sizeof(subtitle_t) * i_max ) ) )
> + {
> + XmlUnLoad( p_demux, sub_nb );
> + stream_Delete( p_stream );
> + free( p_sys );
same
> + return VLC_ENOMEM;
> + }
> + }
> +
> + if( ParseDCSubtitle( p_demux, &p_sys->subtitle[p_sys->i_subtitles],
> + p_sys->i_subtitles, sub_nb ) )
> + break;
> +
> + p_sys->i_subtitles++;
> + }
> +
> + XmlUnLoad( p_demux, sub_nb );
> + stream_Delete(p_stream);
> +
> + return VLC_SUCCESS;
> +}
> +
> +int SubtitleDemux( demux_t *p_demux, int sub_nb )
> +{
> + demux_sub_sys_t *p_sys = p_demux->p_sys->v_sub_sys[sub_nb];
> + int64_t i_maxdate;
> +
> +
> + if( p_sys->i_subtitle >= p_sys->i_subtitles )
> + return 0;
> +
> + i_maxdate = p_sys->i_next_demux_date;
> +
> + if( i_maxdate <= 0 && p_sys->i_subtitle < p_sys->i_subtitles )
> + {
> + /* Should not happen */
> + i_maxdate = p_sys->subtitle[p_sys->i_subtitle].i_start + 1;
> + }
> +
> + while( p_sys->i_subtitle < p_sys->i_subtitles &&
> + p_sys->subtitle[p_sys->i_subtitle].i_start < i_maxdate )
> + {
> + const subtitle_t *p_subtitle = &p_sys->subtitle[p_sys->i_subtitle];
> +
> + block_t *p_block;
> + int i_len = strlen( p_subtitle->psz_text ) + 1;
> +
> + if( i_len <= 1 || p_subtitle->i_start < 0 )
> + {
> + p_sys->i_subtitle++;
> + continue;
> + }
> +
> + if( ( p_block = block_Alloc( i_len ) ) == NULL )
> + {
> + p_sys->i_subtitle++;
> + continue;
> + }
> +
> + p_block->i_dts =
> + p_block->i_pts = VLC_TS_0 + p_subtitle->i_start + p_demux->p_sys->p_dcp->sub_reels[sub_nb].i_correction;
> +
> + if( p_subtitle->i_stop >= 0 && p_subtitle->i_stop >= p_subtitle->i_start )
> + p_block->i_length = p_subtitle->i_stop - p_subtitle->i_start;
> +
> + memcpy( p_block->p_buffer, p_subtitle->psz_text, i_len );
> +
> + es_out_Send( p_demux->out, p_demux->p_sys->p_sub_es, p_block );
> +
> + p_sys->i_subtitle++;
> + }
> +
> + p_sys->i_next_demux_date = 0;
> + return 1;
> +}
> diff --git a/modules/access/dcp/dcpparser.cpp b/modules/access/dcp/dcpparser.cpp
> index cd42922..e68bc46 100644
> --- a/modules/access/dcp/dcpparser.cpp
> +++ b/modules/access/dcp/dcpparser.cpp
> @@ -234,6 +234,8 @@ int AssetMap::Parse ( )
> int index = 0;
> int sum_duration_vid = 0;
> int sum_duration_aud = 0;
> + int sum_duration_sub = 0;
> + int64_t i_conversion = (int64_t)(1000000 / 24);
> string node;
>
> CPL *cpl;
> @@ -268,7 +270,6 @@ int AssetMap::Parse ( )
> }
> }
>
> -
> /* Look for PKLs path */
> if ( (_p_asset_list == NULL) || (_p_asset_list->size() == 0) ) {
> msg_Err( p_demux, "Asset list empty" );
> @@ -345,6 +346,7 @@ int AssetMap::Parse ( )
> Asset *asset;
> struct info_reel video;
> struct info_reel audio;
> + struct info_reel subtitles;
>
> /* Get picture */
> asset = reel->getTrack(TRACK_PICTURE);
> @@ -356,32 +358,51 @@ int AssetMap::Parse ( )
> video.i_duration = asset->getDuration();
> video.i_correction = video.i_entrypoint - sum_duration_vid + video.i_duration;
> video.i_absolute_end = sum_duration_vid;
> + video.i_nb_reel = index;
> p_dcp->video_reels.push_back(video);
> msg_Dbg( this->p_demux, "Video Track: %s",asset->getPath().c_str());
> msg_Dbg( this->p_demux, "Entry point: %i",asset->getEntryPoint());
> }
> +
> /* Get audio */
> asset = reel->getTrack(TRACK_SOUND);
> if (asset != NULL)
> {
> - /*if (!p_dcp->audio_reels.empty())
> - {
> - sum_duration_aud = 0;
> - for (int i = 0; i != p_dcp->audio_reels.size(); ++i)
> - {
> - sum_duration_aud += p_dcp->audio_reels(i).i_duration;
> - }
> - }*/
> sum_duration_aud += asset->getDuration();
> audio.filename = p_dcp->path + asset->getPath();
> audio.i_entrypoint = asset->getEntryPoint();
> audio.i_duration = asset->getDuration();
> audio.i_correction = audio.i_entrypoint - sum_duration_aud + audio.i_duration;
> audio.i_absolute_end = sum_duration_aud;
> + audio.i_nb_reel = index;
> p_dcp->audio_reels.push_back(audio);
> msg_Dbg( this->p_demux, "Audio Track: %s",asset->getPath().c_str());
> msg_Dbg( this->p_demux, "Entry point: %i",asset->getEntryPoint());
> }
> +
> + /* Get subtitle */
> + asset = reel->getTrack(TRACK_SUBTITLE);
> + if (asset != NULL)
> + {
> + sum_duration_sub += asset->getDuration();
> + subtitles.filename = p_dcp->path + asset->getPath();
> + subtitles.i_entrypoint = asset->getEntryPoint();
> + subtitles.i_duration = asset->getDuration();
> + /* Subtitle correction, not the same as for audio and video, unit is 10^(-6)*s */
> + if (index > 0 )
> + {
> + subtitles.i_correction = (p_dcp->video_reels[index-1].i_absolute_end + subtitles.i_entrypoint) * i_conversion;
> + }
> + else
> + {
> + subtitles.i_correction = (subtitles.i_entrypoint) * i_conversion;
> + }
> + subtitles.i_absolute_end = sum_duration_sub;
> + subtitles.i_nb_reel = index;
> + p_dcp->sub_reels.push_back(subtitles);
> + msg_Dbg( this->p_demux, "Subtitle Track: %s",asset->getPath().c_str());
> + msg_Dbg( this->p_demux, "Entry point: %i",asset->getEntryPoint());
> + }
> }
> /* free memory */
> this->CloseXml();
> @@ -448,7 +469,7 @@ int Asset::Parse( xml_reader_t *p_xmlReader, string p_node, int p_type)
> /* Asset tags not in AssetMap */
> break;
> default:
> - msg_Warn(this->p_demux, "Unknow ASSET_TAG: %i", _tag );
> + msg_Warn( this->p_demux, "Unknow ASSET_TAG: %i", _tag );
> break;
> }
> /* break the for loop as a tag is found*/
> @@ -482,6 +503,7 @@ int Asset::Parse( xml_reader_t *p_xmlReader, string p_node, int p_type)
> }
> }
> return -1;
> +
> }
>
>
> @@ -536,7 +558,7 @@ int Asset::ParsePKL( xml_reader_t *p_xmlReader)
> /* Asset tags not in PKL */
> break;
> default:
> - msg_Warn(this->p_demux, "Unknow ASSET_TAG: %i", _tag );
> + msg_Warn( this->p_demux, "Unknow ASSET_TAG: %i", _tag );
> break;
> }
> /* break the for loop as a tag is found*/
> @@ -634,7 +656,6 @@ int AssetMap::ParseAssetList (xml_reader_t *p_xmlReader, const string p_node, in
> string node;
> int type;
> Asset *asset;
> -
> if (p_type != XML_READER_STARTELEM)
> return -1;
> if( p_node != "AssetList" )
> @@ -666,6 +687,7 @@ int AssetMap::ParseAssetList (xml_reader_t *p_xmlReader, const string p_node, in
> }
> }
> return -1;
> +
> }
>
> Asset * AssetMap::getAssetById(AssetList *asset_list, const string p_id)
> @@ -819,7 +841,7 @@ int PKL::Parse()
> this->s_group_id = s_value;
> break;
> default:
> - msg_Warn(this->p_demux, "Unknow PKG_TAG: %i", _tag );
> + msg_Warn( this->p_demux, "Unknow PKG_TAG: %i", _tag );
> break;
> }
> /* break the for loop as a tag is found*/
> @@ -992,6 +1014,10 @@ int Reel::Parse(string p_node, int p_type) {
> int type;
> string s_value;
>
> + this->p_picture_track = NULL;
> + this->p_sound_track = NULL;
> + this->p_subtitle_track = NULL;
> +
> if (p_type != XML_READER_STARTELEM)
> return -1;
> if( p_node != "Reel")
> @@ -1126,19 +1152,19 @@ int Reel::ParseAsset(string p_node, int p_type, TrackType_t e_track) {
> } else if (node == "AnnotationText") {
> if ( ReadEndNode(this->p_xmlReader, node, type, s_value))
> return -1;
> - asset->setAnnotation(s_value);
> + asset->setAnnotation(s_value);
> } else if (node == "IntrinsicDuration") {
> if ( ReadEndNode(this->p_xmlReader, node, type, s_value))
> return -1;
> - asset->setIntrinsicDuration(atoi(s_value.c_str()));
> + 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()));
> + 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()));
> + asset->setDuration(atoi(s_value.c_str()));
> } else if (node == "KeyId") {
> if ( ReadEndNode(this->p_xmlReader, node, type, s_value))
> return -1;
> @@ -1187,6 +1213,7 @@ int Reel::ParseAsset(string p_node, int p_type, TrackType_t e_track) {
> default:
> break;
> }
> +
> return 0;
> }
>
> @@ -1316,7 +1343,7 @@ int CPL::Parse()
> this->s_content_kind = s_value;
> break;
> default:
> - msg_Warn(this->p_demux, "Unknow CPL_TAG: %i", _tag );
> + msg_Warn( this->p_demux, "Unknow CPL_TAG: %i", _tag );
> break;
> }
>
> @@ -1386,6 +1413,7 @@ int CPL::ParseReelList(string p_node, int p_type) {
> break;
> }
> }
> +
> return -1;
> }
>
> diff --git a/modules/access/dcp/dcpparser.h b/modules/access/dcp/dcpparser.h
> index 32059f5..f02a520 100644
> --- a/modules/access/dcp/dcpparser.h
> +++ b/modules/access/dcp/dcpparser.h
> @@ -72,11 +72,12 @@ class PKL;
> /* This struct stores useful information about an MXF for demux() */
> struct info_reel
> {
> + int64_t i_correction; /* entrypoint - sum of previous durations */
> string filename;
> int i_entrypoint;
> int i_duration;
> - int i_correction; /* entrypoint - sum of previous durations */
> - uint32_t i_absolute_end; /* correction + duration */
> + uint32_t i_absolute_end; /* correction + duration */
> + int i_nb_reel; /* number of the reel in the cpl reel list, start at 0 */
> };
>
> /* This struct stores the most important information about the DCP */
> @@ -89,6 +90,7 @@ struct dcp_t
>
> vector<info_reel> audio_reels;
> vector<info_reel> video_reels;
> + vector<info_reel> sub_reels;
>
> dcp_t():
> p_asset_list(NULL) {};
> --
> 1.7.9.5
>
> _______________________________________________
> vlc-devel mailing list
> To unsubscribe or modify your subscription options:
> https://mailman.videolan.org/listinfo/vlc-devel
Regards,
--
Denis Charmet - TypX
Le mauvais esprit est un art de vivre
More information about the vlc-devel
mailing list