@@ -83,6 +83,38 @@ func run(flags *flag.FlagSet) {
8383 }
8484}
8585
86+ type queueCallbacker struct {
87+ el ebml.Element
88+ c listCallbacker
89+
90+ queue []func (v listCallbacker , ctx context.Context ) listCallbacker
91+ }
92+
93+ func (c queueCallbacker ) Found (el ebml.Element , offset int64 , headerSize int ) ebml.Callbacker {
94+ f := func (cc listCallbacker , ctx context.Context ) listCallbacker {
95+ return cc .found (el , offset , headerSize , ctx )
96+ }
97+ c .queue = append (c .queue , f )
98+ return c
99+ }
100+
101+ func (c queueCallbacker ) Decoded (el ebml.Element , offset int64 , headerSize int , val any ) ebml.Callbacker {
102+ if c .el .ID != el .ID {
103+ f := func (cc listCallbacker , ctx context.Context ) listCallbacker {
104+ return cc .decode (el , offset , headerSize , val , ctx )
105+ }
106+
107+ c .queue = append (c .queue , f )
108+ return c
109+ }
110+ ctx := context .WithValue (context .Background (), el .ID , val )
111+
112+ for _ , f := range c .queue {
113+ c .c = f (c .c , ctx )
114+ }
115+ return c .c
116+ }
117+
86118type listCallbacker struct {
87119 w io.Writer
88120 s * matroska.Scanner
@@ -93,177 +125,138 @@ type listCallbacker struct {
93125 showPosition bool
94126 showSize bool
95127 showDataSize bool
96-
97- queueEnabled bool
98- queue []func (v listCallbacker , ctx context.Context ) listCallbacker
99128}
100129
101- func (v listCallbacker ) Found (el ebml.Element , offset int64 , headerSize int ) ebml.Callbacker {
102- callCtx := context . Background ()
130+ func (c listCallbacker ) Found (el ebml.Element , offset int64 , headerSize int ) ebml.Callbacker {
131+ startQueue := false
103132
104133 switch el .ID {
105134 case matroska .IDBlockGroup :
106- v . queueEnabled = true
135+ startQueue = true
107136 }
108137
109- f := func (v listCallbacker , ctx context.Context ) listCallbacker {
110- return v .found (el , offset , headerSize , ctx )
111- }
112-
113- if v .queueEnabled {
114- v .queue = append (v .queue , f )
115- } else {
116- for _ , ff := range v .queue {
117- v = ff (v , callCtx )
118- }
119- v .queue = nil
120- v = f (v , context .Background ())
138+ if startQueue {
139+ return queueCallbacker {el : el , c : c }.Found (el , offset , headerSize )
121140 }
122141
123- return v
142+ return c . found ( el , offset , headerSize , context . Background ())
124143}
125144
126- func (v listCallbacker ) found (el ebml.Element , offset int64 , headerSize int , ctx context.Context ) listCallbacker {
145+ func (c listCallbacker ) found (el ebml.Element , offset int64 , headerSize int , ctx context.Context ) listCallbacker {
127146 sch := el .Schema
128147
129- v .printer .Sub (offset )
130- v .suffix .Reset ()
148+ c .printer .Sub (offset )
149+ c .suffix .Reset ()
131150
132- if v .showPosition {
133- fmt .Fprintf (& v .suffix , ", at %d" , offset )
151+ if c .showPosition {
152+ fmt .Fprintf (& c .suffix , ", at %d" , offset )
134153 }
135- if v .showSize {
154+ if c .showSize {
136155 if el .DataSize == - 1 {
137- fmt .Fprint (& v .suffix , ", size unknown" )
156+ fmt .Fprint (& c .suffix , ", size unknown" )
138157 } else {
139- fmt .Fprintf (& v .suffix , ", size %d" , int64 (headerSize )+ el .DataSize )
158+ fmt .Fprintf (& c .suffix , ", size %d" , int64 (headerSize )+ el .DataSize )
140159 }
141160 }
142- if v .showDataSize {
161+ if c .showDataSize {
143162 if el .DataSize == - 1 {
144- fmt .Fprint (& v .suffix , ", data size unknown" )
163+ fmt .Fprint (& c .suffix , ", data size unknown" )
145164 } else {
146- fmt .Fprintf (& v .suffix , ", data size %d" , el .DataSize )
165+ fmt .Fprintf (& c .suffix , ", data size %d" , el .DataSize )
147166 }
148167 }
149168
150169 switch el .ID {
151170 default :
152171 if sch .Type != ebml .TypeMaster {
153- return v
172+ return c
154173 }
155- v .printer .Printf ("%s%s" , sch .Name , v .suffix .String ())
174+ c .printer .Printf ("%s%s" , sch .Name , c .suffix .String ())
156175 }
157176
158177 if el .DataSize > - 1 {
159178 absoluteEnd := offset + int64 (headerSize ) + el .DataSize
160- v .printer .Add (absoluteEnd )
179+ c .printer .Add (absoluteEnd )
161180 } else {
162- v .printer .Add (- 1 )
181+ c .printer .Add (- 1 )
163182 }
164183
165- return v
184+ return c
166185}
167186
168- func (v listCallbacker ) Decoded (el ebml.Element , offset int64 , headerSize int , val any ) ebml.Callbacker {
169- callCtx := context .Background ()
170-
171- switch el .ID {
172- case matroska .IDBlockGroup :
173- v .queueEnabled = false
174-
175- callCtx = context .WithValue (callCtx , el .ID , val )
176- }
177-
178- f := func (v listCallbacker , ctx context.Context ) listCallbacker {
179- return v .decode (el , offset , headerSize , val , ctx )
180- }
181-
182- if v .queueEnabled {
183- v .queue = append (v .queue , f )
184- } else {
185- for _ , ff := range v .queue {
186- v = ff (v , callCtx )
187- }
188- v .queue = nil
189- v = f (v , callCtx )
190- }
191-
192- return v
187+ func (c listCallbacker ) Decoded (el ebml.Element , offset int64 , headerSize int , val any ) ebml.Callbacker {
188+ return c .decode (el , offset , headerSize , val , context .Background ())
193189}
194190
195- func (v listCallbacker ) decode (el ebml.Element , offset int64 , headerSize int , val any , ctx context.Context ) listCallbacker {
191+ func (c listCallbacker ) decode (el ebml.Element , offset int64 , headerSize int , val any , ctx context.Context ) listCallbacker {
196192 sch := el .Schema
197193 if sch .Type == ebml .TypeMaster {
198- return v
194+ return c
199195 }
200196
201- v .printer .Sub (offset )
202- v .suffix .Reset ()
197+ c .printer .Sub (offset )
198+ c .suffix .Reset ()
203199
204- if v .showPosition {
205- fmt .Fprintf (& v .suffix , ", at %d" , offset )
200+ if c .showPosition {
201+ fmt .Fprintf (& c .suffix , ", at %d" , offset )
206202 }
207- if v .showSize {
203+ if c .showSize {
208204 if el .DataSize == - 1 {
209- fmt .Fprint (& v .suffix , ", size unknown" )
205+ fmt .Fprint (& c .suffix , ", size unknown" )
210206 } else {
211- fmt .Fprintf (& v .suffix , ", size %d" , int64 (headerSize )+ el .DataSize )
207+ fmt .Fprintf (& c .suffix , ", size %d" , int64 (headerSize )+ el .DataSize )
212208 }
213209 }
214- if v .showDataSize {
210+ if c .showDataSize {
215211 if el .DataSize == - 1 {
216- fmt .Fprint (& v .suffix , ", data size unknown" )
212+ fmt .Fprint (& c .suffix , ", data size unknown" )
217213 } else {
218- fmt .Fprintf (& v .suffix , ", data size %d" , el .DataSize )
214+ fmt .Fprintf (& c .suffix , ", data size %d" , el .DataSize )
219215 }
220216 }
221217
222218 switch el .ID {
223219 default :
224220 switch sch .Type {
225221 default :
226- v .printer .Print ("unexpected element " , el .ID )
222+ c .printer .Print ("unexpected element " , el .ID )
227223 case ebml .TypeBinary :
228- v .printer .Printf ("%s%s" , sch .Name , v .suffix .String ())
224+ c .printer .Printf ("%s%s" , sch .Name , c .suffix .String ())
229225 case ebml .TypeString :
230- v .printer .Printf ("%s: %s%s" , sch .Name , val , v .suffix .String ())
226+ c .printer .Printf ("%s: %s%s" , sch .Name , val , c .suffix .String ())
231227 case ebml .TypeUTF8 :
232- v .printer .Printf ("%s: %s%s" , sch .Name , val , v .suffix .String ())
228+ c .printer .Printf ("%s: %s%s" , sch .Name , val , c .suffix .String ())
233229 case ebml .TypeUinteger :
234- v .printer .Printf ("%s: %d%s" , sch .Name , val , v .suffix .String ())
230+ c .printer .Printf ("%s: %d%s" , sch .Name , val , c .suffix .String ())
235231 case ebml .TypeInteger :
236- v .printer .Printf ("%s: %d%s" , sch .Name , val , v .suffix .String ())
232+ c .printer .Printf ("%s: %d%s" , sch .Name , val , c .suffix .String ())
237233 case ebml .TypeFloat :
238- v .printer .Printf ("%s: %f%s" , sch .Name , val , v .suffix .String ())
234+ c .printer .Printf ("%s: %f%s" , sch .Name , val , c .suffix .String ())
239235 case ebml .TypeDate :
240- v .printer .Printf ("%s: %s%s" , sch .Name , val , v .suffix .String ())
236+ c .printer .Printf ("%s: %s%s" , sch .Name , val , c .suffix .String ())
241237 }
242238
243- case matroska .IDBlockGroup :
244- v .queueEnabled = true
245-
246239 case matroska .IDDuration :
247240 // https://www.ietf.org/archive/id/draft-ietf-cellar-matroska-21.html#name-segment-ticks
248- timestampScale := v .s .Info ().TimestampScale
241+ timestampScale := c .s .Info ().TimestampScale
249242 // Stored as a float for some reason
250243 f := val .(float64 )
251244 d := time .Duration (int64 (f * float64 (timestampScale )))
252- v .printer .Printf ("%s: %v%s" , sch .Name , d , v .suffix .String ())
245+ c .printer .Printf ("%s: %v%s" , sch .Name , d , c .suffix .String ())
253246 case matroska .IDTimestamp , matroska .IDCueDuration :
254247 // https://www.ietf.org/archive/id/draft-ietf-cellar-matroska-21.html#name-segment-ticks
255- timestampScale := v .s .Info ().TimestampScale
248+ timestampScale := c .s .Info ().TimestampScale
256249 i := val .(time.Duration )
257250 d := i * timestampScale
258- v .printer .Printf ("%s: %v%s" , sch .Name , d , v .suffix .String ())
251+ c .printer .Printf ("%s: %v%s" , sch .Name , d , c .suffix .String ())
259252 case matroska .IDSeekID :
260253 def , _ := ebml .Definition (matroska .DocType )
261254 i := val .(schema.ElementID )
262255 seekSch , _ := def .Get (i )
263- v .printer .Printf ("%s: %v %s%s" , sch .Name , i , seekSch .Name , v .suffix .String ())
256+ c .printer .Printf ("%s: %v %s%s" , sch .Name , i , seekSch .Name , c .suffix .String ())
264257 case matroska .IDBlockDuration , matroska .IDReferenceBlock :
265258 // https://www.ietf.org/archive/id/draft-ietf-cellar-matroska-21.html#name-track-ticks
266- timestampScale := v .s .Info ().TimestampScale
259+ timestampScale := c .s .Info ().TimestampScale
267260 blockGroup := ctx .Value (matroska .IDBlockGroup ).(matroska.BlockGroup )
268261 block , _ := matroska .ReadBlock (blockGroup .Block , timestampScale )
269262
@@ -278,70 +271,65 @@ func (v listCallbacker) decode(el ebml.Element, offset int64, headerSize int, va
278271 }
279272 // TODO: validate if this would work. I may need the whole BlockGroup.
280273 trackTimestampScale := 1.0
281- for _ , te := range v .s .Tracks ().TrackEntry {
274+ for _ , te := range c .s .Tracks ().TrackEntry {
282275 if te .TrackNumber == block .TrackNumber () {
283276 trackTimestampScale = te .TrackTimestampScale
284277 break
285278 }
286279 }
287280 d := time .Duration (float64 (i ) * float64 (timestampScale ) * trackTimestampScale )
288- v .printer .Printf ("%s: %s%s" , sch .Name , d , v .suffix .String ())
281+ c .printer .Printf ("%s: %s%s" , sch .Name , d , c .suffix .String ())
289282 case matroska .IDBlock :
290283 // https://www.ietf.org/archive/id/draft-ietf-cellar-matroska-21.html#name-block-structure
291- timestampScale := v .s .Info ().TimestampScale
292- blockGroup := ctx .Value (matroska .IDBlockGroup ).(matroska.BlockGroup )
284+ timestampScale := c .s .Info ().TimestampScale
285+ cluster := c .s .Cluster ()
286+ codecDelay := time .Duration (0 )
293287
294288 b := val .([]byte )
295- block , _ := matroska .ReadBlock (b , timestampScale )
289+ block , _ := matroska .ReadBlock (b , cluster . Timestamp )
296290 frames := block .Frames ()
297291
298- blockDuration := time .Second
299- if blockGroup .BlockDuration != nil {
300- blockDuration = time .Duration (* blockGroup .BlockDuration )
301- } else {
302- for _ , te := range v .s .Tracks ().TrackEntry {
303- if te .TrackNumber == block .TrackNumber () {
304- if te .DefaultDuration != nil {
305- blockDuration = time .Duration (* te .DefaultDuration )
306- }
307- break
308- }
292+ for _ , te := range c .s .Tracks ().TrackEntry {
293+ if te .TrackNumber == block .TrackNumber () {
294+ timestampScale = time .Duration (te .TrackTimestampScale * float64 (timestampScale ))
295+ codecDelay = time .Duration (te .CodecDelay )
296+ break
309297 }
310298 }
311299
312- v .printer .Printf ("%s: track number %d, %d frame(s), timestamp %v%s" , sch .Name ,
313- block .TrackNumber (), len (frames ), blockDuration * timestampScale , v .suffix .String ())
314- v .printer .Add (1 )
300+ c .printer .Printf ("%s: track number %d, %d frame(s), timestamp %v%s" , sch .Name ,
301+ block .TrackNumber (), len (frames ), block . Timestamp ( timestampScale ) - codecDelay , c .suffix .String ())
302+ c .printer .Add (1 )
315303 frameOffset := offset + int64 (headerSize ) + el .DataSize
316304 for _ , f := range frames {
317305 frameOffset -= int64 (len (f ))
318306 }
319307 for _ , f := range frames {
320- v .printer .Printf ("Frame at %d size %d" , frameOffset , len (f )) // TODO: incorrect at the moment
308+ c .printer .Printf ("Frame at %d size %d" , frameOffset , len (f )) // TODO: incorrect at the moment
321309 frameOffset += int64 (len (f ))
322310 }
323- v .printer .Sub (1 )
311+ c .printer .Sub (1 )
324312 case matroska .IDSimpleBlock :
325313 // https://www.ietf.org/archive/id/draft-ietf-cellar-matroska-21.html#name-simpleblock-structure
326- timestampScale := v .s .Info ().TimestampScale
314+ timestampScale := c .s .Info ().TimestampScale
327315 b := val .([]byte )
328316 block , _ := matroska .ReadSimpleBlock (b , timestampScale )
329317 frames := block .Frames ()
330- v .printer .Printf ("%s: track number %d, %d frame(s), timestamp %v%s" , sch .Name ,
331- block .TrackNumber (), len (frames ), 0 * timestampScale , v .suffix .String ())
332- v .printer .Add (1 )
318+ c .printer .Printf ("%s: track number %d, %d frame(s), timestamp %v%s" , sch .Name ,
319+ block .TrackNumber (), len (frames ), 0 * timestampScale , c .suffix .String ())
320+ c .printer .Add (1 )
333321 frameOffset := offset + int64 (headerSize ) + el .DataSize
334322 for _ , f := range frames {
335323 frameOffset -= int64 (len (f ))
336324 }
337325 for _ , f := range frames {
338- v .printer .Printf ("Frame at %d size %d" , frameOffset , len (f )) // TODO: incorrect at the moment
326+ c .printer .Printf ("Frame at %d size %d" , frameOffset , len (f )) // TODO: incorrect at the moment
339327 frameOffset += int64 (len (f ))
340328 }
341- v .printer .Sub (1 )
329+ c .printer .Sub (1 )
342330 }
343331
344- return v
332+ return c
345333}
346334
347335type indentedPrinter struct {
0 commit comments