Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
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