[vlc-devel] [PATCH v1 2/3] ogg: Add OggSpots video codec support
Michael Tänzer
neo at nhng.de
Thu Mar 3 20:02:48 CET 2016
---
include/vlc_fourcc.h | 1 +
modules/demux/ogg.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++++-
modules/demux/oggseek.c | 7 ++++
3 files changed, 95 insertions(+), 1 deletion(-)
diff --git a/include/vlc_fourcc.h b/include/vlc_fourcc.h
index 656ec4f..3d14a51 100644
--- a/include/vlc_fourcc.h
+++ b/include/vlc_fourcc.h
@@ -52,6 +52,7 @@
#define VLC_CODEC_THEORA VLC_FOURCC('t','h','e','o')
#define VLC_CODEC_TARKIN VLC_FOURCC('t','a','r','k')
#define VLC_CODEC_DIRAC VLC_FOURCC('d','r','a','c')
+#define VLC_CODEC_OGGSPOTS VLC_FOURCC('S','P','O','T')
#define VLC_CODEC_CAVS VLC_FOURCC('C','A','V','S')
#define VLC_CODEC_NUV VLC_FOURCC('N','J','P','G')
#define VLC_CODEC_RV10 VLC_FOURCC('R','V','1','0')
diff --git a/modules/demux/ogg.c b/modules/demux/ogg.c
index 1f5456a..1175f5b 100644
--- a/modules/demux/ogg.c
+++ b/modules/demux/ogg.c
@@ -38,6 +38,8 @@
#include <ogg/ogg.h>
+#include <limits.h>
+
#include <vlc_codecs.h>
#include <vlc_bits.h>
#include "xiph.h"
@@ -151,6 +153,7 @@ 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 * );
+static bool Ogg_ReadOggSpotsHeader( logical_stream_t *, ogg_packet * );
/* Skeleton */
static void Ogg_ReadSkeletonBones( demux_t *, ogg_packet * );
@@ -639,6 +642,8 @@ static int Demux( demux_t * p_demux )
if( p_stream->fmt.i_cat == SPU_ES )
continue;
+ if( p_stream->fmt.i_codec == VLC_CODEC_OGGSPOTS )
+ continue;
if( p_stream->i_pcr < VLC_TS_0 )
continue;
if ( p_stream->b_finished || p_stream->b_initializing )
@@ -983,6 +988,7 @@ static void Ogg_UpdatePCR( demux_t *p_demux, logical_stream_t *p_stream,
p_stream->fmt.i_codec == VLC_CODEC_VP8 ||
p_stream->fmt.i_codec == VLC_CODEC_DIRAC ||
p_stream->fmt.i_codec == VLC_CODEC_SPEEX ||
+ p_stream->fmt.i_codec == VLC_CODEC_OGGSPOTS ||
(p_stream->b_oggds && p_stream->fmt.i_cat == VIDEO_ES) )
{
p_stream->i_pcr = VLC_TS_0 + Oggseek_GranuleToAbsTimestamp( p_stream,
@@ -1413,7 +1419,8 @@ static void Ogg_DecodePacket( demux_t *p_demux,
p_stream->fmt.i_codec != VLC_CODEC_DAALA &&
p_stream->fmt.i_codec != VLC_CODEC_CMML &&
p_stream->fmt.i_codec != VLC_CODEC_DIRAC &&
- p_stream->fmt.i_codec != VLC_CODEC_KATE )
+ p_stream->fmt.i_codec != VLC_CODEC_KATE &&
+ p_stream->fmt.i_codec != VLC_CODEC_OGGSPOTS )
{
if( p_oggpacket->bytes <= 0 )
{
@@ -2013,6 +2020,22 @@ static int Ogg_FindLogicalStreams( demux_t *p_demux )
p_ogg->i_streams-1 );
Ogg_ReadSkeletonHeader( p_demux, p_stream, &oggpacket );
}
+ /* Check for OggSpots header */
+ else if( oggpacket.bytes >= 8 &&
+ ! memcmp( oggpacket.packet, "SPOTS\0\0", 8 ) )
+ {
+ if ( Ogg_ReadOggSpotsHeader( p_stream, &oggpacket ) )
+ msg_Dbg( p_demux,
+ "found OggSpots header, time resolution: %f",
+ p_stream->f_rate );
+ else
+ {
+ msg_Err( p_demux, "found invalid OggSpots header" );
+ Ogg_LogicalStreamDelete( p_demux, p_stream );
+ p_stream = NULL;
+ p_ogg->i_streams--;
+ }
+ }
else
{
msg_Dbg( p_demux, "stream %d is of unknown type",
@@ -3384,3 +3407,66 @@ static bool Ogg_ReadDiracHeader( logical_stream_t *p_stream,
return true;
}
+
+static bool Ogg_ReadOggSpotsHeader( logical_stream_t *p_stream,
+ ogg_packet *p_oggpacket )
+{
+ uint64_t i_granulerate_numerator;
+ uint64_t i_granulerate_denominator;
+ int i_major;
+ int i_minor;
+
+ p_stream->fmt.i_cat = VIDEO_ES;
+ p_stream->fmt.i_codec = VLC_CODEC_OGGSPOTS;
+
+ /* Signal that we want to keep a backup of the OggSpots
+ * stream headers. They will be used when switching between
+ * audio streams. */
+ p_stream->b_force_backup = true;
+
+ /* Cheat and get additionnal info ;) */
+ if ( p_oggpacket->bytes != 52 )
+ {
+ /* The OggSpots header is always 52 bytes */
+ return false;
+ }
+
+ i_major = GetWLE( &p_oggpacket->packet[ 8] ); /* major version num */
+ i_minor = GetWLE( &p_oggpacket->packet[10] ); /* minor version num */
+ if ( i_major != 0 || i_minor != 1 )
+ {
+ return false;
+ }
+
+ /* Granule rate */
+ i_granulerate_numerator = GetQWLE( &p_oggpacket->packet[12] );
+ i_granulerate_denominator = GetQWLE( &p_oggpacket->packet[20] );
+ if ( i_granulerate_numerator == 0 || i_granulerate_denominator == 0 )
+ {
+ return false;
+ }
+
+ /* The OggSpots spec contained an error and there are implementations out
+ * there that used the wrong value. So we detect that case and switch
+ * numerator and denominator in that case */
+ if ( i_granulerate_numerator == 1 && i_granulerate_denominator == 30 )
+ {
+ i_granulerate_numerator = 30;
+ i_granulerate_denominator = 1;
+ }
+
+ p_stream->f_rate = ((double)i_granulerate_numerator) / i_granulerate_denominator;
+ if ( p_stream->f_rate == 0 )
+ {
+ return false;
+ }
+
+ /* Normalize granulerate */
+ vlc_ureduce(&p_stream->fmt.video.i_frame_rate,
+ &p_stream->fmt.video.i_frame_rate_base,
+ i_granulerate_numerator, i_granulerate_denominator, 0);
+
+ p_stream->i_granule_shift = p_oggpacket->packet[28];
+
+ return true;
+}
diff --git a/modules/demux/oggseek.c b/modules/demux/oggseek.c
index ce9d884..3376aea 100644
--- a/modules/demux/oggseek.c
+++ b/modules/demux/oggseek.c
@@ -738,6 +738,13 @@ int64_t Oggseek_GranuleToAbsTimestamp( logical_stream_t *p_stream,
i_timestamp = i_granule * CLOCK_FREQ / p_stream->f_rate;
break;
}
+ case VLC_CODEC_OGGSPOTS:
+ {
+ if ( b_presentation ) return VLC_TS_INVALID;
+ i_timestamp = ( i_granule >> p_stream->i_granule_shift )
+ * CLOCK_FREQ / p_stream->f_rate;
+ break;
+ }
}
return i_timestamp;
--
2.5.0
More information about the vlc-devel
mailing list