static void Ogg_ReadFlacHeader( demux_t *, logical_stream_t *, ogg_packet * );
static void Ogg_ReadAnnodexHeader( demux_t *, logical_stream_t *, ogg_packet * );
static bool Ogg_ReadDiracHeader( logical_stream_t *, ogg_packet * );
+static bool Ogg_ReadVP8Header( demux_t *, logical_stream_t *, ogg_packet * );
static void Ogg_ReadSkeletonHeader( demux_t *, logical_stream_t *, ogg_packet * );
/* Skeleton */
audio->i_original_channels = pi_channels_map[chans];
}
+/* Special TS value: don't send or derive any pts/pcr from it.
+ Represents TS state prior first known valid timestamp */
+#define VLC_TS_UNKNOWN (VLC_TS_INVALID - 1)
+
/*****************************************************************************
* Open: initializes ogg demux structures
*****************************************************************************/
stream_Control( p_demux->s, STREAM_CAN_SEEK, &b_canseek );
if ( b_canseek )
Oggseek_ProbeEnd( p_demux );
- es_out_Control( p_demux->out, ES_OUT_SET_PCR, VLC_TS_0 );
}
else
{
- es_out_Control( p_demux->out, ES_OUT_RESET_PCR );
p_sys->b_chained_boundary = false;
}
}
- if ( p_sys->b_preparsing_done )
+ if ( p_sys->b_preparsing_done && !p_sys->b_es_created )
{
- for ( int i=0; i < p_sys->i_streams; i++ )
- {
- if ( !p_sys->pp_stream[i]->p_es )
- {
- Ogg_CreateES( p_demux );
- break;
- }
- }
+ Ogg_CreateES( p_demux );
+ p_sys->b_es_created = true;
}
/*
for( i_stream = 0; i_stream < p_sys->i_streams; i_stream++ )
{
logical_stream_t *p_stream = p_sys->pp_stream[i_stream];
- if ( p_stream->b_have_updated_format )
- {
- p_stream->b_have_updated_format = false;
- if ( p_stream->p_skel ) Ogg_ApplySkeleton( p_stream );
- if ( p_stream->p_es )
- {
- msg_Dbg( p_demux, "Resetting format for stream %d", i_stream );
- es_out_Control( p_demux->out, ES_OUT_SET_ES_FMT,
- p_stream->p_es, &p_stream->fmt );
- }
- }
+ Ogg_ApplySkeleton( p_stream );
}
}
}
ogg_stream_reset_serialno( &p_stream->os, ogg_page_serialno( &p_sys->current_page ) );
p_stream->b_reinit = true;
- p_stream->i_pcr = VLC_TS_0;
- p_stream->i_interpolated_pcr = VLC_TS_0;
+ p_stream->i_pcr = VLC_TS_UNKNOWN;
+ p_stream->i_interpolated_pcr = VLC_TS_UNKNOWN;
p_stream->i_previous_granulepos = -1;
es_out_Control( p_demux->out, ES_OUT_SET_PCR, VLC_TS_0);
}
if( p_stream->fmt.i_codec == VLC_CODEC_VORBIS ||
p_stream->fmt.i_codec == VLC_CODEC_SPEEX ||
p_stream->fmt.i_codec == VLC_CODEC_OPUS ||
+ p_stream->fmt.i_codec == VLC_CODEC_VP8 ||
p_stream->fmt.i_codec == VLC_CODEC_FLAC )
{
if( ogg_stream_packetout( &p_stream->os, &oggpacket ) > 0 )
/* if a page was waiting, it's now processed */
p_sys->b_page_waiting = false;
- p_sys->b_preparsing_done = true;
+ if ( p_sys->p_skelstream && !p_sys->p_skelstream->b_finished )
+ p_sys->b_preparsing_done = false;
+ else
+ p_sys->b_preparsing_done = true;
- p_sys->i_pcr = -1;
+ /* We will consider the lowest PCR among tracks, because the audio core badly
+ * handles PCR rewind (mute)
+ */
+ mtime_t i_pcr_candidate = VLC_TS_INVALID;
for( i_stream = 0; i_stream < p_sys->i_streams; i_stream++ )
{
logical_stream_t *p_stream = p_sys->pp_stream[i_stream];
- if ( p_stream->b_force_backup )
+ if ( p_sys->b_preparsing_done && p_stream->b_initializing )
{
/* We have 1 or more streams needing more than 1 page for preparsing */
p_sys->b_preparsing_done = false;
if( p_stream->fmt.i_cat == SPU_ES )
continue;
- if( p_stream->i_interpolated_pcr < 0 )
+ if( p_stream->i_interpolated_pcr < VLC_TS_0 )
+ continue;
+ if ( p_stream->b_finished || p_stream->b_initializing )
continue;
- if( p_sys->i_pcr < 0 || p_stream->i_interpolated_pcr < p_sys->i_pcr )
- p_sys->i_pcr = p_stream->i_interpolated_pcr;
+ if( i_pcr_candidate < VLC_TS_0
+ || p_stream->i_interpolated_pcr <= i_pcr_candidate )
+ {
+ i_pcr_candidate = p_stream->i_interpolated_pcr;
+ }
}
- if( p_sys->i_pcr >= 0 && ! b_skipping )
- es_out_Control( p_demux->out, ES_OUT_SET_PCR, VLC_TS_0 + p_sys->i_pcr );
+ if ( i_pcr_candidate > VLC_TS_INVALID && p_sys->i_pcr != i_pcr_candidate )
+ {
+ p_sys->i_pcr = i_pcr_candidate;
+ if( ! b_skipping )
+ es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_sys->i_pcr );
+ }
return 1;
}
/* we'll trash all the data until we find the next pcr */
p_stream->b_reinit = true;
- p_stream->i_pcr = -1;
- p_stream->i_interpolated_pcr = -1;
+ p_stream->i_pcr = VLC_TS_UNKNOWN;
+ p_stream->i_interpolated_pcr = VLC_TS_UNKNOWN;
p_stream->i_previous_granulepos = -1;
ogg_stream_reset( &p_stream->os );
}
for( int i=0; i<p_sys->i_streams; i++ )
{
logical_stream_t *p_candidate = p_sys->pp_stream[i];
+ if ( !p_candidate->p_es ) continue;
bool b_selected = false;
es_out_Control( p_demux->out, ES_OUT_GET_ES_STATE,
p_stream->i_end_trim = 0;
/* Convert the granulepos into a pcr */
- if( p_oggpacket->granulepos >= 0 )
+ if ( p_oggpacket->granulepos == 0 )
+ {
+ /* We're in headers, and we haven't parsed 1st data packet yet */
+ p_stream->i_pcr = VLC_TS_UNKNOWN;
+ p_stream->i_interpolated_pcr = VLC_TS_UNKNOWN;
+ }
+ else if( p_oggpacket->granulepos > 0 )
{
if( p_stream->fmt.i_codec == VLC_CODEC_THEORA ||
p_stream->fmt.i_codec == VLC_CODEC_KATE ||
+ p_stream->fmt.i_codec == VLC_CODEC_VP8 ||
p_stream->fmt.i_codec == VLC_CODEC_DIRAC )
{
p_stream->i_pcr = Oggseek_GranuleToAbsTimestamp( p_stream,
else
{
int duration;
- p_stream->i_pcr = -1;
+ p_stream->i_pcr = VLC_TS_INVALID;
/* no granulepos available, try to interpolate the pcr.
* If we can't then don't touch the old value. */
VLC_TS_0 + sample * CLOCK_FREQ / p_stream->f_rate;
p_stream->i_interpolated_pcr += p_ogg->i_pcr_offset;
}
- else if( p_stream->fmt.i_bitrate )
+ else if( p_stream->fmt.i_bitrate && p_stream->i_pcr > VLC_TS_UNKNOWN )
{
p_stream->i_interpolated_pcr +=
( p_oggpacket->bytes * CLOCK_FREQ /
block_t *p_block;
bool b_selected;
int i_header_len = 0;
- mtime_t i_pts = -1, i_interpolated_pts;
+ mtime_t i_pts = VLC_TS_UNKNOWN, i_interpolated_pts;
demux_sys_t *p_ogg = p_demux->p_sys;
if( p_oggpacket->bytes >= 7 &&
Ogg_ReadSkeletonIndex( p_demux, p_oggpacket );
return;
}
+ else if( p_stream->fmt.i_codec == VLC_CODEC_VP8 &&
+ p_oggpacket->bytes >= 7 &&
+ !memcmp( p_oggpacket->packet, "OVP80\x02\x20", 7 ) )
+ {
+ Ogg_ReadVP8Header( p_demux, p_stream, p_oggpacket );
+ return;
+ }
if( p_stream->fmt.i_codec == VLC_CODEC_SUBT && p_oggpacket->bytes > 0 &&
p_oggpacket->packet[0] & PACKET_TYPE_BITS ) return;
else
p_stream->fmt.i_extra = 0;
- if( Ogg_LogicalStreamResetEsFormat( p_demux, p_stream ) )
- {
- if ( p_ogg->p_skelstream )
- {
- /* We delay until eos is reached on skeleton.
- * There should only be headers, as no data page is
- * allowed before skeleton's eos.
- * Skeleton data is appended to fmt on skeleton eos.
- */
- p_stream->b_have_updated_format = true;
- }
- else
- {
- if ( p_stream->p_es )
- /* Otherwise we set config from first headers */
- es_out_Control( p_demux->out, ES_OUT_SET_ES_FMT,
- p_stream->p_es, &p_stream->fmt );
- }
- }
if( p_stream->i_headers > 0 )
Ogg_ExtractMeta( p_demux, & p_stream->fmt,
p_stream->p_headers, p_stream->i_headers );
if( p_stream->fmt.i_codec == VLC_CODEC_VORBIS ||
p_stream->fmt.i_codec == VLC_CODEC_SPEEX ||
p_stream->fmt.i_codec == VLC_CODEC_OPUS ||
+ p_stream->fmt.i_codec == VLC_CODEC_VP8 ||
p_stream->fmt.i_codec == VLC_CODEC_FLAC )
{
- if( p_stream->i_pcr >= 0 )
+ if( p_stream->i_pcr > VLC_TS_INVALID )
{
- /* This is for streams where the granulepos of the header packets
- * doesn't match these of the data packets (eg. ogg web radios). */
- if( p_stream->i_previous_pcr == 0 &&
- p_stream->i_pcr > 3 * DEFAULT_PTS_DELAY )
- {
-
- /* Call the pace control */
- es_out_Control( p_demux->out, ES_OUT_SET_PCR,
- VLC_TS_0 + p_stream->i_pcr );
- }
-
p_stream->i_previous_pcr = p_stream->i_pcr;
-
/* The granulepos is the end date of the sample */
i_pts = p_stream->i_pcr;
}
i_interpolated_pts = p_stream->i_interpolated_pcr;
Ogg_UpdatePCR( p_demux, p_stream, p_oggpacket );
- /* SPU streams are typically discontinuous, do not mind large gaps */
- if( p_stream->fmt.i_cat != SPU_ES )
- {
- if( p_stream->i_pcr >= 0 )
- {
- /* This is for streams where the granulepos of the header packets
- * doesn't match these of the data packets (eg. ogg web radios). */
- if( p_stream->i_previous_pcr == 0 &&
- p_stream->i_pcr > 3 * DEFAULT_PTS_DELAY )
- {
-
- /* Call the pace control */
- es_out_Control( p_demux->out, ES_OUT_SET_PCR, VLC_TS_0 + p_stream->i_pcr );
- }
- }
- }
-
if( p_stream->fmt.i_codec != VLC_CODEC_VORBIS &&
p_stream->fmt.i_codec != VLC_CODEC_SPEEX &&
p_stream->fmt.i_codec != VLC_CODEC_OPUS &&
+ p_stream->fmt.i_codec != VLC_CODEC_VP8 &&
p_stream->fmt.i_codec != VLC_CODEC_FLAC &&
p_stream->i_pcr >= 0 )
{
else if( p_stream->fmt.i_codec == VLC_CODEC_OPUS )
p_block->i_nb_samples = Ogg_OpusPacketDuration( p_stream, p_oggpacket );
-
/* Normalize PTS */
- if( i_pts == VLC_TS_INVALID ) i_pts = VLC_TS_0;
- else if( i_pts == -1 && i_interpolated_pts == VLC_TS_INVALID )
- i_pts = VLC_TS_0;
- else if( i_pts == -1 && (p_stream->fmt.i_cat == VIDEO_ES || p_stream->fmt.i_codec == VLC_CODEC_OPUS) )
- i_pts = i_interpolated_pts; /* FIXME : why is this incorrect for vorbis? */
- else if( i_pts == -1 ) i_pts = VLC_TS_INVALID;
+ if( i_pts == VLC_TS_UNKNOWN )
+ i_pts = VLC_TS_INVALID;
if( p_stream->fmt.i_cat == AUDIO_ES )
{
if( -1 != p_oggpacket->granulepos )
p_block->i_pts = u_pnum * CLOCK_FREQ / p_stream->f_rate / 2;
}
+ else if( p_stream->fmt.i_codec == VLC_CODEC_VP8 )
+ {
+ p_block->i_pts = p_stream->i_interpolated_pcr;
+ p_block->i_dts = p_block->i_pts;
+ if( p_oggpacket->granulepos > 0 && Ogg_IsKeyFrame( p_stream, p_oggpacket ) )
+ {
+ p_block->i_flags |= BLOCK_FLAG_TYPE_I;
+ }
+ }
else
{
p_block->i_dts = i_pts;
if( p_stream->fmt.i_codec != VLC_CODEC_VORBIS &&
p_stream->fmt.i_codec != VLC_CODEC_SPEEX &&
p_stream->fmt.i_codec != VLC_CODEC_OPUS &&
+ p_stream->fmt.i_codec != VLC_CODEC_VP8 &&
p_stream->fmt.i_codec != VLC_CODEC_FLAC &&
p_stream->fmt.i_codec != VLC_CODEC_TARKIN &&
p_stream->fmt.i_codec != VLC_CODEC_THEORA &&
p_block->i_buffer = 0;
}
- if ( p_stream->b_reusing )
- {
- p_stream->b_reusing = false;
- p_block->i_flags |= BLOCK_FLAG_DISCONTINUITY;
- }
if( p_stream->fmt.i_codec == VLC_CODEC_TARKIN )
{
memcpy( p_block->p_buffer, p_oggpacket->packet + i_header_len,
p_oggpacket->bytes - i_header_len );
+ if ( p_ogg->i_streams == 1 && p_block->i_pts > VLC_TS_INVALID && p_ogg->i_pcr < VLC_TS_0 )
+ {
+ p_ogg->i_pcr = p_block->i_pts;
+ es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_ogg->i_pcr );
+ }
+
if ( p_stream->p_es )
{
/* Because ES creation is delayed for preparsing */
es_format_Init( &p_stream->fmt, 0, 0 );
es_format_Init( &p_stream->fmt_old, 0, 0 );
+ p_stream->b_initializing = true;
/* Setup the logical stream */
p_stream->i_serial_no = ogg_page_serialno( &p_ogg->current_page );
"found tarkin header, bitrate: %i, rate: %f",
p_stream->fmt.i_bitrate, p_stream->f_rate );
}
+ /* Check for VP8 header */
+ else if( oggpacket.bytes >= 26 &&
+ ! memcmp( oggpacket.packet, "OVP80", 5 ) )
+ {
+ if ( Ogg_ReadVP8Header( p_demux, p_stream, &oggpacket ) )
+ msg_Dbg( p_demux, "found VP8 header "
+ "fps: %f, width:%i; height:%i",
+ p_stream->f_rate,
+ p_stream->fmt.video.i_width,
+ p_stream->fmt.video.i_height );
+ else
+ p_stream->fmt.i_cat = UNKNOWN_ES;
+ }
/* Check for Annodex header */
else if( oggpacket.bytes >= 7 &&
! memcmp( oggpacket.packet, "Annodex", 7 ) )
}
/* we'll need to get all headers */
- p_ogg->pp_stream[i_stream]->b_initializing |= p_ogg->pp_stream[i_stream]->b_force_backup;
+ p_ogg->pp_stream[i_stream]->b_initializing &= p_ogg->pp_stream[i_stream]->b_force_backup;
if( Ogg_ReadPage( p_demux, &p_ogg->current_page ) != VLC_SUCCESS )
return VLC_EGENERIC;
{
logical_stream_t *p_stream = p_ogg->pp_stream[i_stream];
- if ( p_stream->p_es == NULL )
+ if ( p_stream->p_es == NULL && !p_stream->b_finished )
{
/* Better be safe than sorry when possible with ogm */
if( p_stream->fmt.i_codec == VLC_CODEC_MPGA ||
p_stream->b_finished = false;
p_stream->b_reinit = false;
p_stream->b_initializing = false;
- p_stream->b_reusing = true;
+ bool b_resetdecoder = Ogg_LogicalStreamResetEsFormat( p_demux, p_stream );
es_format_Copy( &p_stream->fmt_old, &p_old_stream->fmt );
p_old_stream->p_es = NULL;
p_old_stream = NULL;
- es_out_Control( p_demux->out, ES_OUT_SET_ES_FMT,
- p_stream->p_es, &p_stream->fmt );
+ if ( b_resetdecoder )
+ {
+ es_out_Control( p_demux->out, ES_OUT_SET_ES_FMT,
+ p_stream->p_es, &p_stream->fmt );
+ }
}
else
{
p_ogg->i_bitrate += p_stream->fmt.i_bitrate;
p_stream->i_pcr = p_stream->i_previous_pcr =
- p_stream->i_interpolated_pcr = -1;
+ p_stream->i_interpolated_pcr = VLC_TS_UNKNOWN;
p_stream->b_reinit = false;
}
p_ogg->skeleton.major = 0;
p_ogg->skeleton.minor = 0;
p_ogg->b_preparsing_done = false;
+ p_ogg->b_es_created = false;
p_ogg->i_pcr_offset = p_ogg->i_pcr;
/* */
return !b_compatible;
}
-static void Ogg_ExtractXiphMeta( demux_t *p_demux, es_format_t *p_fmt,
- const void *p_headers, unsigned i_headers, unsigned i_skip )
+
+static void Ogg_ExtractComments( demux_t *p_demux, es_format_t *p_fmt,
+ const void *p_headers, unsigned i_headers )
{
demux_sys_t *p_ogg = p_demux->p_sys;
+ int i_cover_score = 0;
+ int i_cover_idx = 0;
+ float pf_replay_gain[AUDIO_REPLAY_GAIN_MAX];
+ float pf_replay_peak[AUDIO_REPLAY_GAIN_MAX];
+ for(int i=0; i< AUDIO_REPLAY_GAIN_MAX; i++ )
+ {
+ pf_replay_gain[i] = 0;
+ pf_replay_peak[i] = 0;
+ }
+ vorbis_ParseComment( &p_ogg->p_meta, p_headers, i_headers,
+ &p_ogg->i_attachments, &p_ogg->attachments,
+ &i_cover_score, &i_cover_idx,
+ &p_ogg->i_seekpoints, &p_ogg->pp_seekpoints,
+ &pf_replay_gain, &pf_replay_peak );
+ if( p_ogg->p_meta != NULL && i_cover_idx < p_ogg->i_attachments )
+ {
+ char psz_url[128];
+ snprintf( psz_url, sizeof(psz_url), "attachment://%s",
+ p_ogg->attachments[i_cover_idx]->psz_name );
+ vlc_meta_Set( p_ogg->p_meta, vlc_meta_ArtworkURL, psz_url );
+ }
- unsigned pi_size[XIPH_MAX_HEADER_COUNT];
- void *pp_data[XIPH_MAX_HEADER_COUNT];
- unsigned i_count;
- if( xiph_SplitHeaders( pi_size, pp_data, &i_count, i_headers, p_headers ) )
- return;
-
- /* TODO how to handle multiple comments properly ? */
- if( i_count >= 2 && pi_size[1] > i_skip )
+ for ( int i=0; i<AUDIO_REPLAY_GAIN_MAX;i++ )
{
- int i_cover_score = 0;
- int i_cover_idx = 0;
- float pf_replay_gain[AUDIO_REPLAY_GAIN_MAX];
- float pf_replay_peak[AUDIO_REPLAY_GAIN_MAX];
- for(int i=0; i< AUDIO_REPLAY_GAIN_MAX; i++ )
- {
- pf_replay_gain[i] = 0;
- pf_replay_peak[i] = 0;
- }
- vorbis_ParseComment( &p_ogg->p_meta, (uint8_t*)pp_data[1] + i_skip, pi_size[1] - i_skip,
- &p_ogg->i_attachments, &p_ogg->attachments,
- &i_cover_score, &i_cover_idx,
- &p_ogg->i_seekpoints, &p_ogg->pp_seekpoints,
- &pf_replay_gain, &pf_replay_peak );
- if( p_ogg->p_meta != NULL && i_cover_idx < p_ogg->i_attachments )
+ if ( pf_replay_gain[i] != 0 )
{
- char psz_url[128];
- snprintf( psz_url, sizeof(psz_url), "attachment://%s",
- p_ogg->attachments[i_cover_idx]->psz_name );
- vlc_meta_Set( p_ogg->p_meta, vlc_meta_ArtworkURL, psz_url );
+ p_fmt->audio_replay_gain.pb_gain[i] = true;
+ p_fmt->audio_replay_gain.pf_gain[i] = pf_replay_gain[i];
+ msg_Dbg( p_demux, "setting replay gain %d to %f", i, pf_replay_gain[i] );
}
-
- for ( int i=0; i<AUDIO_REPLAY_GAIN_MAX;i++ )
+ if ( pf_replay_peak[i] != 0 )
{
- if ( pf_replay_gain[i] != 0 )
- {
- p_fmt->audio_replay_gain.pb_gain[i] = true;
- p_fmt->audio_replay_gain.pf_gain[i] = pf_replay_gain[i];
- msg_Dbg( p_demux, "setting replay gain %d to %f", i, pf_replay_gain[i] );
- }
- if ( pf_replay_peak[i] != 0 )
- {
- p_fmt->audio_replay_gain.pb_peak[i] = true;
- p_fmt->audio_replay_gain.pf_peak[i] = pf_replay_peak[i];
- msg_Dbg( p_demux, "setting replay peak %d to %f", i, pf_replay_gain[i] );
- }
+ p_fmt->audio_replay_gain.pb_peak[i] = true;
+ p_fmt->audio_replay_gain.pf_peak[i] = pf_replay_peak[i];
+ msg_Dbg( p_demux, "setting replay peak %d to %f", i, pf_replay_gain[i] );
}
}
p_demux->info.i_update |= INPUT_UPDATE_TITLE_LIST;
}
}
+
+static void Ogg_ExtractXiphMeta( demux_t *p_demux, es_format_t *p_fmt,
+ const void *p_headers, unsigned i_headers, unsigned i_skip )
+{
+ unsigned pi_size[XIPH_MAX_HEADER_COUNT];
+ void *pp_data[XIPH_MAX_HEADER_COUNT];
+ unsigned i_count;
+
+ if( xiph_SplitHeaders( pi_size, pp_data, &i_count, i_headers, p_headers ) )
+ return;
+ /* TODO how to handle multiple comments properly ? */
+ if( i_count >= 2 && pi_size[1] > i_skip )
+ {
+ Ogg_ExtractComments( p_demux, p_fmt, (uint8_t*)pp_data[1] + i_skip, pi_size[1] - i_skip );
+ }
+}
+
static void Ogg_ExtractMeta( demux_t *p_demux, es_format_t *p_fmt, const uint8_t *p_headers, int i_headers )
{
demux_sys_t *p_ogg = p_demux->p_sys;
case VLC_CODEC_SPEEX:
Ogg_ExtractXiphMeta( p_demux, p_fmt, p_headers, i_headers, 0 );
break;
-
+ case VLC_CODEC_VP8:
+ Ogg_ExtractComments( p_demux, p_fmt, p_headers, i_headers );
+ break;
/* N headers with the 2° one being the comments */
case VLC_CODEC_KATE:
/* 1 byte for header type, 7 bytes for magic, 1 reserved zero byte */
p_stream->f_rate = p_stream->fmt.audio.i_rate =
oggpack_read( &opb, 32 );
oggpack_adv( &opb, 32 );
- p_stream->fmt.i_bitrate = oggpack_read( &opb, 32 );
+ p_stream->fmt.i_bitrate = oggpack_read( &opb, 32 ); /* is signed 32 */
+ if( p_stream->fmt.i_bitrate > INT32_MAX ) p_stream->fmt.i_bitrate = 0;
}
static void Ogg_ReadSpeexHeader( logical_stream_t *p_stream,
}
}
+static bool Ogg_ReadVP8Header( demux_t *p_demux, logical_stream_t *p_stream,
+ ogg_packet *p_oggpacket )
+{
+ switch( p_oggpacket->packet[5] )
+ {
+ /* STREAMINFO */
+ case 0x01:
+ /* Mapping version */
+ if ( p_oggpacket->packet[6] != 0x01 || p_oggpacket->packet[7] != 0x00 )
+ return false;
+ p_stream->fmt.i_cat = VIDEO_ES;
+ p_stream->fmt.i_codec = VLC_CODEC_VP8;
+ p_stream->i_granule_shift = 32;
+ p_stream->fmt.video.i_width = GetWBE( &p_oggpacket->packet[8] );
+ p_stream->fmt.video.i_height = GetWBE( &p_oggpacket->packet[10] );
+ p_stream->fmt.video.i_sar_num = GetDWBE( &p_oggpacket->packet[12 - 1] ) & 0x0FFF;
+ p_stream->fmt.video.i_sar_den = GetDWBE( &p_oggpacket->packet[15 - 1] ) & 0x0FFF;
+ p_stream->fmt.video.i_frame_rate = GetDWBE( &p_oggpacket->packet[18] );
+ p_stream->fmt.video.i_frame_rate_base = GetDWBE( &p_oggpacket->packet[22] );
+ p_stream->f_rate = (double) p_stream->fmt.video.i_frame_rate / p_stream->fmt.video.i_frame_rate_base;
+ return true;
+ /* METADATA */
+ case 0x02:
+ Ogg_ExtractMeta( p_demux, & p_stream->fmt,
+ p_oggpacket->packet + 7, p_oggpacket->bytes - 7 );
+ return true;
+ default:
+ return false;
+ }
+}
+
static void Ogg_ApplyContentType( logical_stream_t *p_stream, const char* psz_value,
bool *b_force_backup, bool *b_packet_out )
{
free( p_stream->fmt.psz_description );
p_stream->fmt.psz_description = strdup("OGG Kate Overlay (Unsupported)");
}
+ else if( !strncmp(psz_value, "video/x-vp8", 11) )
+ {
+ p_stream->fmt.i_cat = VIDEO_ES;
+ p_stream->fmt.i_codec = VLC_CODEC_VP8;
+ }
}
static void Ogg_ReadAnnodexHeader( demux_t *p_demux,