Commit be3f9e2d authored by Derk-Jan Hartman's avatar Derk-Jan Hartman

avformat: Support for AVChapters.

parent b149f96f
......@@ -35,6 +35,7 @@
#include <vlc_stream.h>
#include <vlc_meta.h>
#include <vlc_input.h>
#include <vlc_charset.h>
/* ffmpeg header */
#if defined(HAVE_LIBAVFORMAT_AVFORMAT_H)
......@@ -56,6 +57,10 @@
# define HAVE_FFMPEG_CODEC_ATTACHMENT 1
#endif
#if (LIBAVFORMAT_VERSION_INT >= ((52<<16)+(15<<8)+0) )
# define HAVE_FFMPEG_CHAPTERS 1
#endif
/*****************************************************************************
* demux_sys_t: demux descriptor
*****************************************************************************/
......@@ -79,6 +84,9 @@ struct demux_sys_t
int i_attachments;
input_attachment_t **attachments;
/* Only one title with seekpoints possible atm. */
input_title_t *p_title;
};
/*****************************************************************************
......@@ -90,6 +98,8 @@ static int Control( demux_t *p_demux, int i_query, va_list args );
static int IORead( void *opaque, uint8_t *buf, int buf_size );
static offset_t IOSeek( void *opaque, offset_t offset, int whence );
static void UpdateSeekPoint( demux_t *p_demux, int64_t i_time );
/*****************************************************************************
* Open
*****************************************************************************/
......@@ -99,8 +109,9 @@ int OpenDemux( vlc_object_t *p_this )
demux_sys_t *p_sys;
AVProbeData pd;
AVInputFormat *fmt;
unsigned int i;
bool b_avfmt_nofile;
unsigned int i;
bool b_avfmt_nofile;
int64_t i_start_time = -1;
/* Init Probe data */
pd.filename = p_demux->psz_path;
......@@ -163,6 +174,7 @@ int OpenDemux( vlc_object_t *p_this )
p_sys->i_pcr_tk = -1;
p_sys->i_pcr = -1;
TAB_INIT( p_sys->i_attachments, p_sys->attachments);
p_sys->p_title = NULL;
/* Create I/O wrapper */
p_sys->io_buffer_size = 32768; /* FIXME */
......@@ -298,17 +310,37 @@ int OpenDemux( vlc_object_t *p_this )
psz_type, (char*)&fcc );
TAB_APPEND( p_sys->i_tk, p_sys->tk, es );
}
if( p_sys->ic->start_time != (int64_t)AV_NOPTS_VALUE )
i_start_time = p_sys->ic->start_time * 1000000 / AV_TIME_BASE;
msg_Dbg( p_demux, "AVFormat supported stream" );
msg_Dbg( p_demux, " - format = %s (%s)",
p_sys->fmt->name, p_sys->fmt->long_name );
msg_Dbg( p_demux, " - start time = %"PRId64,
( p_sys->ic->start_time != (int64_t)AV_NOPTS_VALUE ) ?
p_sys->ic->start_time * 1000000 / AV_TIME_BASE : -1 );
msg_Dbg( p_demux, " - start time = %"PRId64, i_start_time );
msg_Dbg( p_demux, " - duration = %"PRId64,
( p_sys->ic->duration != (int64_t)AV_NOPTS_VALUE ) ?
p_sys->ic->duration * 1000000 / AV_TIME_BASE : -1 );
#if HAVE_FFMPEG_CHAPTERS
p_sys->p_title = vlc_input_title_New();
for( i = 0; i < p_sys->ic->nb_chapters; i++ )
{
seekpoint_t *s = vlc_seekpoint_New();
if( p_sys->ic->chapters[i]->title )
{
s->psz_name = strdup( p_sys->ic->chapters[i]->title );
EnsureUTF8( s->psz_name );
msg_Dbg( p_demux, " - chapter %d: %s", i, s->psz_name );
}
s->i_time_offset = p_sys->ic->chapters[i]->start * 1000000 *
p_sys->ic->chapters[i]->time_base.num /
p_sys->ic->chapters[i]->time_base.den -
(i_start_time != -1 ? i_start_time : 0 );
TAB_APPEND( p_sys->p_title->i_seekpoint, p_sys->p_title->seekpoint, s );
}
#endif
return VLC_SUCCESS;
}
......@@ -332,6 +364,9 @@ void CloseDemux( vlc_object_t *p_this )
free( p_sys->attachments[i] );
TAB_CLEAN( p_sys->i_attachments, p_sys->attachments);
if( p_sys->p_title )
vlc_input_title_Delete( p_sys->p_title );
free( p_sys->io_buffer );
free( p_sys );
}
......@@ -397,10 +432,34 @@ static int Demux( demux_t *p_demux )
}
es_out_Send( p_demux->out, p_sys->tk[pkt.stream_index], p_frame );
UpdateSeekPoint( p_demux, p_sys->i_pcr);
av_free_packet( &pkt );
return 1;
}
static void UpdateSeekPoint( demux_t *p_demux, int64_t i_time )
{
demux_sys_t *p_sys = p_demux->p_sys;
int i;
if( !p_sys->p_title )
return;
for( i = 0; i < p_sys->p_title->i_seekpoint; i++ )
{
if( i_time < p_sys->p_title->seekpoint[i]->i_time_offset )
break;
}
i--;
if( i != p_demux->info.i_seekpoint && i >= 0 )
{
p_demux->info.i_seekpoint = i;
p_demux->info.i_update |= INPUT_UPDATE_SEEKPOINT;
}
}
/*****************************************************************************
* Control:
*****************************************************************************/
......@@ -444,12 +503,12 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
(av_seek_frame( p_sys->ic, -1, i64, 0 ) < 0) )
{
int64_t i_size = stream_Size( p_demux->s );
i64 = (int64_t)i_size * f;
msg_Warn( p_demux, "DEMUX_SET_BYTE_POSITION: %"PRId64, i64 );
if( av_seek_frame( p_sys->ic, -1, i64, AVSEEK_FLAG_BYTE ) < 0 )
if( av_seek_frame( p_sys->ic, -1, (i_size * f), AVSEEK_FLAG_BYTE ) < 0 )
return VLC_EGENERIC;
}
UpdateSeekPoint( p_demux, i64 );
es_out_Control( p_demux->out, ES_OUT_RESET_PCR );
p_sys->i_pcr = -1; /* Invalidate time display */
}
......@@ -483,6 +542,7 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
}
es_out_Control( p_demux->out, ES_OUT_RESET_PCR );
p_sys->i_pcr = -1; /* Invalidate time display */
UpdateSeekPoint( p_demux, i64 );
return VLC_SUCCESS;
case DEMUX_GET_META:
......@@ -526,6 +586,53 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
return VLC_SUCCESS;
}
case DEMUX_GET_TITLE_INFO:
{
input_title_t ***ppp_title = (input_title_t***)va_arg( args, input_title_t*** );
int *pi_int = (int*)va_arg( args, int* );
int *pi_title_offset = (int*)va_arg( args, int* );
int *pi_seekpoint_offset = (int*)va_arg( args, int* );
if( !p_sys->p_title )
return VLC_EGENERIC;
*pi_int = 1;
*ppp_title = malloc( sizeof( input_title_t**) );
(*ppp_title)[0] = vlc_input_title_Duplicate( p_sys->p_title );
*pi_title_offset = 0;
*pi_seekpoint_offset = 0;
return VLC_SUCCESS;
}
case DEMUX_SET_TITLE:
{
const int i_title = (int)va_arg( args, int );
if( !p_sys->p_title || i_title != 0 )
return VLC_EGENERIC;
return VLC_SUCCESS;
}
case DEMUX_SET_SEEKPOINT:
{
const int i_seekpoint = (int)va_arg( args, int );
if( !p_sys->p_title )
return VLC_EGENERIC;
i64 = p_sys->p_title->seekpoint[i_seekpoint]->i_time_offset *AV_TIME_BASE / 1000000;
if( p_sys->ic->start_time != (int64_t)AV_NOPTS_VALUE )
i64 += p_sys->ic->start_time;
msg_Warn( p_demux, "DEMUX_SET_TIME: %"PRId64, i64 );
if( av_seek_frame( p_sys->ic, -1, i64, 0 ) < 0 )
{
return VLC_EGENERIC;
}
es_out_Control( p_demux->out, ES_OUT_RESET_PCR );
p_sys->i_pcr = -1; /* Invalidate time display */
UpdateSeekPoint( p_demux, i64 );
return VLC_SUCCESS;
}
default:
return VLC_EGENERIC;
}
......
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