Merge branch 'feature-vlc-mkv-opus' into 'belenos'
vlc: add support for opus codec in mkv container More info: https://trisquel.info/en/forum/playing-vp9-opus-trisquel-7 See merge request !111
This commit is contained in:
commit
5964b3a14a
2 changed files with 272 additions and 0 deletions
|
|
@ -0,0 +1,243 @@
|
|||
From 46fe18b280ed5825fd701edeedb2f5c24de001a2 Mon Sep 17 00:00:00 2001
|
||||
From: Denis Charmet <typx@dinauz.org>
|
||||
Date: Sat, 9 Nov 2013 16:53:06 +0100
|
||||
Subject: [PATCH] Implement basic Opus support in MKV
|
||||
|
||||
---
|
||||
modules/codec/opus.c | 5 ++++
|
||||
modules/demux/mkv/matroska_segment.cpp | 22 +++++++++++++++-
|
||||
modules/demux/mkv/matroska_segment_parse.cpp | 36 +++++++++++++++++++++++++
|
||||
modules/demux/mkv/mkv.cpp | 39 +++++++++++++++++++---------
|
||||
modules/demux/mkv/mkv.hpp | 6 +++--
|
||||
5 files changed, 94 insertions(+), 16 deletions(-)
|
||||
|
||||
diff --git a/modules/codec/opus.c b/modules/codec/opus.c
|
||||
index d4e5f88..8802d49 100644
|
||||
--- a/modules/codec/opus.c
|
||||
+++ b/modules/codec/opus.c
|
||||
@@ -386,6 +386,11 @@ static block_t *DecodePacket( decoder_t *p_dec, ogg_packet *p_oggpacket,
|
||||
if(spp>0)spp*=opus_packet_get_samples_per_frame(p_oggpacket->packet,48000);
|
||||
if(spp<120||spp>120*48)return NULL;
|
||||
|
||||
+ /* Since the information isn't always available at the demux level
|
||||
+ * use the packet's sample number */
|
||||
+ if(!i_nb_samples)
|
||||
+ i_nb_samples = spp;
|
||||
+
|
||||
block_t *p_aout_buffer=decoder_NewAudioBuffer( p_dec, spp );
|
||||
if ( !p_aout_buffer )
|
||||
{
|
||||
diff --git a/modules/demux/mkv/matroska_segment.cpp b/modules/demux/mkv/matroska_segment.cpp
|
||||
index 756a9c5..5e71206 100644
|
||||
--- a/modules/demux/mkv/matroska_segment.cpp
|
||||
+++ b/modules/demux/mkv/matroska_segment.cpp
|
||||
@@ -929,10 +929,22 @@ void matroska_segment_c::Seek( mtime_t i_date, mtime_t i_time_offset, int64_t i_
|
||||
/* now parse until key frame */
|
||||
const int es_types[3] = { VIDEO_ES, AUDIO_ES, SPU_ES };
|
||||
i_cat = es_types[0];
|
||||
+ mtime_t i_seek_preroll = 0;
|
||||
for( int i = 0; i < 2; i_cat = es_types[++i] )
|
||||
{
|
||||
for( i_track = 0; i_track < tracks.size(); i_track++ )
|
||||
{
|
||||
+ if( tracks[i_track]->i_seek_preroll )
|
||||
+ {
|
||||
+ bool b_enabled;
|
||||
+ if( es_out_Control( sys.demuxer.out,
|
||||
+ ES_OUT_GET_ES_STATE,
|
||||
+ tracks[i_track]->p_es,
|
||||
+ &b_enabled ) == VLC_SUCCESS &&
|
||||
+ b_enabled )
|
||||
+ i_seek_preroll = __MAX( i_seek_preroll,
|
||||
+ tracks[i_track]->i_seek_preroll );
|
||||
+ }
|
||||
if( tracks[i_track]->fmt.i_cat == i_cat )
|
||||
{
|
||||
spoint * seekpoint = new spoint(i_track, i_seek_time, i_seek_position, i_seek_position);
|
||||
@@ -968,7 +980,7 @@ void matroska_segment_c::Seek( mtime_t i_date, mtime_t i_time_offset, int64_t i_
|
||||
es_out_Control( sys.demuxer.out, ES_OUT_SET_NEXT_DISPLAY_TIME, i_date );
|
||||
return;
|
||||
}
|
||||
-
|
||||
+ i_date -= i_seek_preroll;
|
||||
for(;;)
|
||||
{
|
||||
do
|
||||
@@ -1201,6 +1213,7 @@ int matroska_segment_c::BlockGet( KaxBlock * & pp_block, KaxSimpleBlock * & pp_s
|
||||
*pb_key_picture = true;
|
||||
*pb_discardable_picture = false;
|
||||
size_t i_tk;
|
||||
+ *pi_duration = 0;
|
||||
|
||||
for( ;; )
|
||||
{
|
||||
@@ -1407,6 +1420,13 @@ int matroska_segment_c::BlockGet( KaxBlock * & pp_block, KaxSimpleBlock * & pp_s
|
||||
}
|
||||
}
|
||||
}
|
||||
+#if LIBMATROSKA_VERSION >= 0x010401
|
||||
+ else if( MKV_IS_ID( el, KaxDiscardPadding ) )
|
||||
+ {
|
||||
+ KaxDiscardPadding &dp = *(KaxDiscardPadding*) el;
|
||||
+ *pi_duration -= int64(dp);
|
||||
+ }
|
||||
+#endif
|
||||
break;
|
||||
default:
|
||||
msg_Err( &sys.demuxer, "invalid level = %d", i_level );
|
||||
diff --git a/modules/demux/mkv/matroska_segment_parse.cpp b/modules/demux/mkv/matroska_segment_parse.cpp
|
||||
index c9d2c9d..7b4c359 100644
|
||||
--- a/modules/demux/mkv/matroska_segment_parse.cpp
|
||||
+++ b/modules/demux/mkv/matroska_segment_parse.cpp
|
||||
@@ -30,6 +30,7 @@
|
||||
|
||||
extern "C" {
|
||||
#include "../vobsub.h"
|
||||
+#include "../xiph.h"
|
||||
}
|
||||
|
||||
#include <vlc_codecs.h>
|
||||
@@ -401,6 +402,21 @@ void matroska_segment_c::ParseTrackEntry( KaxTrackEntry *m )
|
||||
|
||||
msg_Dbg( &sys.demuxer, "| | | + Track Overlay=%u", uint32( tovr ) );
|
||||
}
|
||||
+#if LIBMATROSKA_VERSION >= 0x010401
|
||||
+ else if( MKV_IS_ID( l, KaxCodecDelay ) )
|
||||
+ {
|
||||
+ KaxCodecDelay &codecdelay = *(KaxCodecDelay*)l;
|
||||
+ tk->i_codec_delay = uint64_t( codecdelay ) / 1000;
|
||||
+ msg_Dbg( &sys.demuxer, "| | | + Track Codec Delay =%"PRIu64,
|
||||
+ tk->i_codec_delay );
|
||||
+ }
|
||||
+ else if( MKV_IS_ID( l, KaxSeekPreRoll ) )
|
||||
+ {
|
||||
+ KaxSeekPreRoll &spr = *(KaxSeekPreRoll*)l;
|
||||
+ tk->i_seek_preroll = uint64_t(spr) / 1000;
|
||||
+ msg_Dbg( &sys.demuxer, "| | | + Track Seek Preroll =%"PRIu64, tk->i_seek_preroll );
|
||||
+ }
|
||||
+#endif
|
||||
else if( MKV_IS_ID( l, KaxContentEncodings ) )
|
||||
{
|
||||
EbmlMaster *cencs = static_cast<EbmlMaster*>(l);
|
||||
@@ -1477,6 +1493,26 @@ int32_t matroska_segment_c::TrackInit( mkv_track_t * p_tk )
|
||||
p_tk->fmt.i_codec = VLC_CODEC_VORBIS;
|
||||
fill_extra_data( p_tk, 0 );
|
||||
}
|
||||
+ else if( !strncmp( p_tk->psz_codec, "A_OPUS", 6 ) )
|
||||
+ {
|
||||
+ p_tk->fmt.i_codec = VLC_CODEC_OPUS;
|
||||
+ if( !p_tk->fmt.audio.i_rate )
|
||||
+ {
|
||||
+ msg_Err( &sys.demuxer,"No sampling rate, defaulting to 48kHz");
|
||||
+ p_tk->fmt.audio.i_rate = 48000;
|
||||
+ }
|
||||
+ const uint8_t tags[16] = {'O','p','u','s','T','a','g','s',
|
||||
+ 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
+ unsigned ps[2] = { p_tk->i_extra_data, 16 };
|
||||
+ const void *pkt[2] = { (const void *)p_tk->p_extra_data,
|
||||
+ (const void *) tags };
|
||||
+
|
||||
+ if( xiph_PackHeaders( &p_tk->fmt.i_extra,
|
||||
+ &p_tk->fmt.p_extra,
|
||||
+ ps, pkt, 2 ) )
|
||||
+ msg_Err( &sys.demuxer, "Couldn't pack OPUS headers");
|
||||
+
|
||||
+ }
|
||||
else if( !strncmp( p_tk->psz_codec, "A_AAC/MPEG2/", strlen( "A_AAC/MPEG2/" ) ) ||
|
||||
!strncmp( p_tk->psz_codec, "A_AAC/MPEG4/", strlen( "A_AAC/MPEG4/" ) ) )
|
||||
{
|
||||
diff --git a/modules/demux/mkv/mkv.cpp b/modules/demux/mkv/mkv.cpp
|
||||
index 6398409..7d42d83 100644
|
||||
--- a/modules/demux/mkv/mkv.cpp
|
||||
+++ b/modules/demux/mkv/mkv.cpp
|
||||
@@ -499,10 +499,8 @@ void BlockDecode( demux_t *p_demux, KaxBlock *block, KaxSimpleBlock *simpleblock
|
||||
msg_Err( p_demux, "unknown track number" );
|
||||
return;
|
||||
}
|
||||
- if( i_pts + i_duration < p_sys->i_start_pts && tk->fmt.i_cat == AUDIO_ES )
|
||||
- {
|
||||
- return; /* discard audio packets that shouldn't be rendered */
|
||||
- }
|
||||
+
|
||||
+ i_pts -= tk->i_codec_delay;
|
||||
|
||||
if ( tk->fmt.i_cat != NAV_ES )
|
||||
{
|
||||
@@ -592,9 +590,10 @@ void BlockDecode( demux_t *p_demux, KaxBlock *block, KaxSimpleBlock *simpleblock
|
||||
{
|
||||
memcpy( p_block->p_buffer, tk->p_compression_data->GetBuffer(), tk->p_compression_data->GetSize() );
|
||||
}
|
||||
-
|
||||
- if( tk->fmt.i_codec == VLC_CODEC_COOK ||
|
||||
- tk->fmt.i_codec == VLC_CODEC_ATRAC3 )
|
||||
+ switch( tk->fmt.i_codec )
|
||||
+ {
|
||||
+ case VLC_CODEC_COOK:
|
||||
+ case VLC_CODEC_ATRAC3:
|
||||
{
|
||||
handle_real_audio(p_demux, tk, p_block, i_pts);
|
||||
block_Release(p_block);
|
||||
@@ -602,6 +601,27 @@ void BlockDecode( demux_t *p_demux, KaxBlock *block, KaxSimpleBlock *simpleblock
|
||||
i_pts + ( mtime_t )( tk->i_default_duration / 1000 ):
|
||||
VLC_TS_INVALID;
|
||||
continue;
|
||||
+ }
|
||||
+ case VLC_CODEC_SPU:
|
||||
+ if( strcmp( tk->psz_codec, "S_VOBSUB" ) )
|
||||
+ p_block->i_length = i_duration * tk-> f_timecodescale *
|
||||
+ (double) p_segment->i_timescale / 1000.0;
|
||||
+ break;
|
||||
+ case VLC_CODEC_OPUS:
|
||||
+ if( i_duration > 0 )
|
||||
+ {
|
||||
+ mtime_t i_length = i_duration * tk-> f_timecodescale *
|
||||
+ (double) p_segment->i_timescale / 1000.0;
|
||||
+ p_block->i_nb_samples = i_length * tk->fmt.audio.i_rate
|
||||
+ / CLOCK_FREQ;
|
||||
+ break;
|
||||
+ }
|
||||
+ else if( i_duration < 0 )
|
||||
+ {
|
||||
+ /* Opus uses p_block->i_length to handle discard padding */
|
||||
+ p_block->i_length = -1 * i_duration * tk->fmt.audio.i_rate
|
||||
+ / CLOCK_FREQ;
|
||||
+ }
|
||||
}
|
||||
|
||||
if ( tk->fmt.i_cat == NAV_ES )
|
||||
@@ -643,11 +663,6 @@ void BlockDecode( demux_t *p_demux, KaxBlock *block, KaxSimpleBlock *simpleblock
|
||||
#if 0
|
||||
msg_Dbg( p_demux, "block i_dts: %"PRId64" / i_pts: %"PRId64, p_block->i_dts, p_block->i_pts);
|
||||
#endif
|
||||
- if( strcmp( tk->psz_codec, "S_VOBSUB" ) )
|
||||
- {
|
||||
- p_block->i_length = i_duration * tk-> f_timecodescale * (double) p_segment->i_timescale / 1000.0;
|
||||
- }
|
||||
-
|
||||
/* FIXME remove when VLC_TS_INVALID work is done */
|
||||
if( i == 0 || p_block->i_dts > VLC_TS_INVALID )
|
||||
p_block->i_dts += VLC_TS_0;
|
||||
diff --git a/modules/demux/mkv/mkv.hpp b/modules/demux/mkv/mkv.hpp
|
||||
index efc88b3..7cae3e7 100644
|
||||
--- a/modules/demux/mkv/mkv.hpp
|
||||
+++ b/modules/demux/mkv/mkv.hpp
|
||||
@@ -188,8 +188,6 @@ class PrivateTrackData
|
||||
|
||||
struct mkv_track_t
|
||||
{
|
||||
-// ~mkv_track_t();
|
||||
-
|
||||
bool b_default;
|
||||
bool b_enabled;
|
||||
bool b_forced;
|
||||
@@ -237,6 +235,10 @@ struct mkv_track_t
|
||||
uint32_t i_encoding_scope;
|
||||
KaxContentCompSettings *p_compression_data;
|
||||
|
||||
+ /* Matroska 4 new elements used by Opus */
|
||||
+ mtime_t i_seek_preroll;
|
||||
+ mtime_t i_codec_delay;
|
||||
+
|
||||
};
|
||||
|
||||
struct mkv_index_t
|
||||
29
helpers/make-vlc
Normal file
29
helpers/make-vlc
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# Copyright (C) 2015 Santiago Rodríguez <santi@trisquel.info>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
|
||||
VERSION=1
|
||||
|
||||
. ./config
|
||||
|
||||
#Enable OPUS support in mkv container
|
||||
patch -p1 < $DATA/46fe18b280ed5825fd701edeedb2f5c24de001a2_without_xiph.patch
|
||||
|
||||
changelog "Added opus support to mkv container"
|
||||
|
||||
compile
|
||||
Loading…
Add table
Add a link
Reference in a new issue