Commit a625064c authored by Steve Lhomme's avatar Steve Lhomme

mkv.cpp: use the title feature to display the segment hierarchy

parent dd2aecae
...@@ -528,6 +528,7 @@ public: ...@@ -528,6 +528,7 @@ public:
void RefreshChapters( ); void RefreshChapters( );
mtime_t Duration() const; mtime_t Duration() const;
void PublishChapters( input_title_t & title ); void PublishChapters( input_title_t & title );
std::string GetMainName() const;
bool b_ordered; bool b_ordered;
}; };
...@@ -695,6 +696,7 @@ public: ...@@ -695,6 +696,7 @@ public:
,p_editions(NULL) ,p_editions(NULL)
,i_current_edition(-1) ,i_current_edition(-1)
,psz_current_chapter(NULL) ,psz_current_chapter(NULL)
,i_sys_title(0)
{ {
linked_segments.push_back( p_segment ); linked_segments.push_back( p_segment );
...@@ -716,11 +718,6 @@ public: ...@@ -716,11 +718,6 @@ public:
return (*p_editions)[i_current_edition]; return (*p_editions)[i_current_edition];
return NULL; return NULL;
} }
inline bool EditionIsOrdered() const
{
return (p_editions->size() != 0 && i_current_edition >= 0 && (*p_editions)[i_current_edition]->b_ordered);
}
matroska_segment_c * Segment() const matroska_segment_c * Segment() const
{ {
...@@ -755,18 +752,20 @@ public: ...@@ -755,18 +752,20 @@ public:
void UpdateCurrentToChapter( demux_t & demux ); void UpdateCurrentToChapter( demux_t & demux );
void PrepareChapters( ); void PrepareChapters( );
bool Select( input_title_t & title );
chapter_item_c *BrowseCodecPrivate( unsigned int codec_id, chapter_item_c *BrowseCodecPrivate( unsigned int codec_id,
bool (*match)(const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size ), bool (*match)(const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size ),
const void *p_cookie, const void *p_cookie,
size_t i_cookie_size ); size_t i_cookie_size );
std::vector<chapter_edition_c*> *p_editions;
int i_sys_title;
protected: protected:
std::vector<matroska_segment_c*> linked_segments; std::vector<matroska_segment_c*> linked_segments;
std::vector<KaxSegmentUID> linked_uids; std::vector<KaxSegmentUID> linked_uids;
size_t i_current_segment; size_t i_current_segment;
std::vector<chapter_edition_c*> *p_editions;
int i_current_edition; int i_current_edition;
chapter_item_c *psz_current_chapter; chapter_item_c *psz_current_chapter;
...@@ -805,7 +804,7 @@ public: ...@@ -805,7 +804,7 @@ public:
,i_start_pts(0) ,i_start_pts(0)
,i_chapter_time(0) ,i_chapter_time(0)
,meta(NULL) ,meta(NULL)
,title(NULL) ,i_current_title(0)
,p_current_segment(NULL) ,p_current_segment(NULL)
,f_duration(-1.0) ,f_duration(-1.0)
{} {}
...@@ -830,7 +829,8 @@ public: ...@@ -830,7 +829,8 @@ public:
vlc_meta_t *meta; vlc_meta_t *meta;
input_title_t *title; std::vector<input_title_t> titles; // matroska editions
size_t i_current_title;
std::vector<matroska_stream_c*> streams; std::vector<matroska_stream_c*> streams;
std::vector<matroska_segment_c*> opened_segments; std::vector<matroska_segment_c*> opened_segments;
...@@ -1062,23 +1062,26 @@ static int Control( demux_t *p_demux, int i_query, va_list args ) ...@@ -1062,23 +1062,26 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
return VLC_SUCCESS; return VLC_SUCCESS;
case DEMUX_GET_TITLE_INFO: case DEMUX_GET_TITLE_INFO:
if( p_sys->title && p_sys->title->i_seekpoint > 0 ) if( p_sys->titles.size() )
{ {
input_title_t ***ppp_title = (input_title_t***)va_arg( args, input_title_t*** ); input_title_t ***ppp_title = (input_title_t***)va_arg( args, input_title_t*** );
int *pi_int = (int*)va_arg( args, int* ); int *pi_int = (int*)va_arg( args, int* );
*pi_int = 1; *pi_int = p_sys->titles.size();
*ppp_title = (input_title_t**)malloc( sizeof( input_title_t**) ); *ppp_title = (input_title_t**)malloc( sizeof( input_title_t**) * p_sys->titles.size() );
(*ppp_title)[0] = vlc_input_title_Duplicate( p_sys->title ); for( size_t i = 0; i < p_sys->titles.size(); i++ )
{
(*ppp_title)[i] = vlc_input_title_Duplicate( &p_sys->titles[i] );
}
return VLC_SUCCESS; return VLC_SUCCESS;
} }
return VLC_EGENERIC; return VLC_EGENERIC;
case DEMUX_SET_TITLE: case DEMUX_SET_TITLE:
/* TODO handle editions as titles & DVD titles as well */ /* TODO handle editions as titles */
if( p_sys->title && p_sys->title->i_seekpoint > 0 ) if( p_sys->titles.size() && p_sys->titles[p_sys->i_current_title].i_seekpoint > 0 )
{ {
return VLC_SUCCESS; return VLC_SUCCESS;
} }
...@@ -1087,9 +1090,9 @@ static int Control( demux_t *p_demux, int i_query, va_list args ) ...@@ -1087,9 +1090,9 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
case DEMUX_SET_SEEKPOINT: case DEMUX_SET_SEEKPOINT:
i_skp = (int)va_arg( args, int ); i_skp = (int)va_arg( args, int );
if( p_sys->title && i_skp < p_sys->title->i_seekpoint) if( p_sys->titles.size() && i_skp < p_sys->titles[p_sys->i_current_title].i_seekpoint)
{ {
Seek( p_demux, (int64_t)p_sys->title->seekpoint[i_skp]->i_time_offset, -1, NULL); Seek( p_demux, (int64_t)p_sys->titles[p_sys->i_current_title].seekpoint[i_skp]->i_time_offset, -1, NULL);
p_demux->info.i_seekpoint |= INPUT_UPDATE_SEEKPOINT; p_demux->info.i_seekpoint |= INPUT_UPDATE_SEEKPOINT;
p_demux->info.i_seekpoint = i_skp; p_demux->info.i_seekpoint = i_skp;
return VLC_SUCCESS; return VLC_SUCCESS;
...@@ -1804,29 +1807,20 @@ void virtual_segment_c::PrepareChapters( ) ...@@ -1804,29 +1807,20 @@ void virtual_segment_c::PrepareChapters( )
} }
} }
bool virtual_segment_c::Select( input_title_t & title ) std::string chapter_edition_c::GetMainName() const
{ {
if ( Edition() != NULL ) return "";
Edition()->PublishChapters( title );
return true;
} }
void chapter_edition_c::PublishChapters( input_title_t & title ) void chapter_edition_c::PublishChapters( input_title_t & title )
{ {
if ( title.seekpoint != NULL )
free( title.seekpoint );
title.i_seekpoint = 0;
title.seekpoint = NULL;
chapter_item_c::PublishChapters( title, 0 ); chapter_item_c::PublishChapters( title, 0 );
} }
void chapter_item_c::PublishChapters( input_title_t & title, int i_level ) void chapter_item_c::PublishChapters( input_title_t & title, int i_level )
{ {
// add support for meta-elements from codec like DVD Titles // add support for meta-elements from codec like DVD Titles
if ( psz_name == "" || !b_display_seekpoint ) if ( !b_display_seekpoint || psz_name == "" )
{ {
psz_name = GetCodecName(); psz_name = GetCodecName();
if ( psz_name != "" ) if ( psz_name != "" )
...@@ -1994,11 +1988,33 @@ std::string dvd_chapter_codec_c::GetCodecName() const ...@@ -1994,11 +1988,33 @@ std::string dvd_chapter_codec_c::GetCodecName() const
if ( p_data[0] == 0x28 ) if ( p_data[0] == 0x28 )
{ {
uint16_t i_title = (p_data[1] << 8) + p_data[2]; uint16_t i_title = (p_data[1] << 8) + p_data[2];
char psz_str[6]; char psz_str[11];
sprintf( psz_str, " %d", i_title ); sprintf( psz_str, " %d ---", i_title );
result = N_("DVD Title"); result = N_("--- DVD Title");
result += psz_str;
}
else if ( p_data[0] == 0x2A )
{
char psz_str[11];
sprintf( psz_str, " (%c%c) ---", p_data[1], p_data[2] );
result = N_("--- DVD Menu");
result += psz_str; result += psz_str;
} }
else if ( p_data[0] == 0x30 )
{
if ( p_data[1] == 0x00 )
result = N_("First Played");
else if ( p_data[1] == 0xC0 )
result = N_("Video Manager");
else if ( p_data[1] == 0x80 )
{
uint16_t i_title = (p_data[2] << 8) + p_data[3];
char psz_str[20];
sprintf( psz_str, " %d -----", i_title );
result = N_("----- Title");
result += psz_str;
}
}
} }
return result; return result;
...@@ -2110,7 +2126,7 @@ static int Demux( demux_t *p_demux) ...@@ -2110,7 +2126,7 @@ static int Demux( demux_t *p_demux)
if( p_sys->i_pts >= p_sys->i_start_pts ) if( p_sys->i_pts >= p_sys->i_start_pts )
p_vsegment->UpdateCurrentToChapter( *p_demux ); p_vsegment->UpdateCurrentToChapter( *p_demux );
if ( p_vsegment->EditionIsOrdered() && p_vsegment->CurrentChapter() == NULL ) if ( p_vsegment->Edition() && p_vsegment->Edition()->b_ordered && p_vsegment->CurrentChapter() == NULL )
{ {
/* nothing left to read in this ordered edition */ /* nothing left to read in this ordered edition */
if ( !p_vsegment->SelectNext() ) if ( !p_vsegment->SelectNext() )
...@@ -2132,7 +2148,7 @@ static int Demux( demux_t *p_demux) ...@@ -2132,7 +2148,7 @@ static int Demux( demux_t *p_demux)
if( p_segmet->BlockGet( &block, &i_block_ref1, &i_block_ref2, &i_block_duration ) ) if( p_segmet->BlockGet( &block, &i_block_ref1, &i_block_ref2, &i_block_duration ) )
{ {
if ( p_vsegment->EditionIsOrdered() ) if ( p_vsegment->Edition() && p_vsegment->Edition()->b_ordered )
{ {
const chapter_item_c *p_chap = p_vsegment->CurrentChapter(); const chapter_item_c *p_chap = p_vsegment->CurrentChapter();
// check if there are more chapters to read // check if there are more chapters to read
...@@ -3313,11 +3329,6 @@ void matroska_segment_c::ParseChapterAtom( int i_level, KaxChapterAtom *ca, chap ...@@ -3313,11 +3329,6 @@ void matroska_segment_c::ParseChapterAtom( int i_level, KaxChapterAtom *ca, chap
{ {
size_t i, j; size_t i, j;
if( sys.title == NULL )
{
sys.title = vlc_input_title_New();
}
msg_Dbg( &sys.demuxer, "| | | + ChapterAtom (level=%d)", i_level ); msg_Dbg( &sys.demuxer, "| | | + ChapterAtom (level=%d)", i_level );
for( i = 0; i < ca->ListSize(); i++ ) for( i = 0; i < ca->ListSize(); i++ )
{ {
...@@ -3778,7 +3789,7 @@ bool matroska_segment_c::PreloadFamily( const matroska_segment_c & of_segment ) ...@@ -3778,7 +3789,7 @@ bool matroska_segment_c::PreloadFamily( const matroska_segment_c & of_segment )
// preload all the linked segments for all preloaded segments // preload all the linked segments for all preloaded segments
void demux_sys_t::PreloadLinked( matroska_segment_c *p_segment ) void demux_sys_t::PreloadLinked( matroska_segment_c *p_segment )
{ {
size_t i_preloaded, i; size_t i_preloaded, i, j;
virtual_segment_c *p_seg; virtual_segment_c *p_seg;
p_current_segment = VirtualFromSegments( p_segment ); p_current_segment = VirtualFromSegments( p_segment );
...@@ -3799,7 +3810,43 @@ void demux_sys_t::PreloadLinked( matroska_segment_c *p_segment ) ...@@ -3799,7 +3810,43 @@ void demux_sys_t::PreloadLinked( matroska_segment_c *p_segment )
} }
} while ( i_preloaded ); // worst case: will stop when all segments are found as family related } while ( i_preloaded ); // worst case: will stop when all segments are found as family related
// TODO publish all editions of all usable segment // publish all editions of all usable segment
for ( i=0; i< used_segments.size(); i++ )
{
p_seg = used_segments[i];
if ( p_seg->p_editions != NULL )
{
std::string sz_name;
input_title_t *p_title = vlc_input_title_New();
p_seg->i_sys_title = i;
for ( j=0; j<p_seg->p_editions->size(); j++ )
{
if ( p_title->psz_name == NULL )
{
sz_name = (*p_seg->p_editions)[j]->GetMainName();
if ( sz_name != "" )
p_title->psz_name = strdup( sz_name.c_str() );
}
chapter_edition_c *p_edition = (*p_seg->p_editions)[j];
p_edition->PublishChapters( *p_title );
}
// create a name if there is none
if ( p_title->psz_name == NULL )
{
sz_name = N_("Segment ");
char psz_str[6];
sprintf( psz_str, "%d", i );
sz_name += psz_str;
p_title->psz_name = strdup( sz_name.c_str() );
}
titles.push_back( *p_title );
}
}
} }
bool demux_sys_t::IsUsedSegment( matroska_segment_c &segment ) const bool demux_sys_t::IsUsedSegment( matroska_segment_c &segment ) const
...@@ -3846,7 +3893,7 @@ bool demux_sys_t::PreparePlayback( ) ...@@ -3846,7 +3893,7 @@ bool demux_sys_t::PreparePlayback( )
p_current_segment->Segment()->Select( 0 ); p_current_segment->Segment()->Select( 0 );
return p_current_segment->Select( *title ); return true;
} }
bool matroska_segment_c::CompareSegmentUIDs( const matroska_segment_c * p_item_a, const matroska_segment_c * p_item_b ) bool matroska_segment_c::CompareSegmentUIDs( const matroska_segment_c * p_item_a, const matroska_segment_c * p_item_b )
...@@ -4154,7 +4201,7 @@ void virtual_segment_c::Seek( demux_t & demuxer, mtime_t i_date, mtime_t i_time_ ...@@ -4154,7 +4201,7 @@ void virtual_segment_c::Seek( demux_t & demuxer, mtime_t i_date, mtime_t i_time_
// find the actual time for an ordered edition // find the actual time for an ordered edition
if ( psz_chapter == NULL ) if ( psz_chapter == NULL )
{ {
if ( EditionIsOrdered() ) if ( Edition() && Edition()->b_ordered )
{ {
/* 1st, we need to know in which chapter we are */ /* 1st, we need to know in which chapter we are */
psz_chapter = (*p_editions)[i_current_edition]->FindTimecode( i_date ); psz_chapter = (*p_editions)[i_current_edition]->FindTimecode( i_date );
...@@ -4330,6 +4377,7 @@ bool dvd_command_interpretor_c::Interpret( const binary * p_command, size_t i_si ...@@ -4330,6 +4377,7 @@ bool dvd_command_interpretor_c::Interpret( const binary * p_command, size_t i_si
if ( p_segment != sys.p_current_segment ) if ( p_segment != sys.p_current_segment )
{ {
sys.p_current_segment = p_segment; sys.p_current_segment = p_segment;
sys.i_current_title = p_segment->i_sys_title + 1;
sys.PreparePlayback(); sys.PreparePlayback();
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment