4545#define ID_SIMPLEBLOCK 0xA3u
4646#define ID_BLOCKGROUP 0xA0u
4747#define ID_BLOCK 0xA1u
48+ #define ID_DISCARDPADDING 0x75A2u
4849
4950#define TRACKTYPE_VIDEO 1
5051#define TRACKTYPE_AUDIO 2
@@ -119,6 +120,14 @@ static uint64_t be_uint(const uint8_t *p, size_t n)
119120 return v ;
120121}
121122
123+ /* Signed big-endian integer element payload (sign-extended). */
124+ static int64_t ebml_sint (const uint8_t * p , size_t n )
125+ {
126+ uint64_t v = be_uint (p , n );
127+ int shift = (int )(64 - 8 * n );
128+ return ((int64_t )(v << shift )) >> shift ;
129+ }
130+
122131/* Read a big-endian IEEE float/double (Matroska float element). */
123132static double be_float (const uint8_t * p , size_t n )
124133{
@@ -156,6 +165,8 @@ struct rwebm
156165 int64_t cluster_ts ; /* current cluster timestamp (ticks) */
157166 /* Lacing: a SimpleBlock may carry several frames; we emit them one at a
158167 * time, so remember where we are within a block. */
168+ int64_t pending_discard ; /* DiscardPadding for the next Block */
169+ int64_t lace_discard ; /* padding owed by the laced block */
159170 const uint8_t * lace_data ; /* payload after the block header */
160171 const uint32_t * lace_sizes ; /* not used (see note); kept simple */
161172 int lace_count ;
@@ -298,6 +309,31 @@ void rwebm_rewind(rwebm_t *webm)
298309 webm -> lace_index = 0 ;
299310}
300311
312+ /* DiscardPadding for the Block just parsed: the element may sit before
313+ * the Block (already captured in pending_discard) or after it within
314+ * the same BlockGroup, so scan the remaining group siblings. */
315+ static int64_t webm_group_discard (rwebm_t * webm , const uint8_t * p ,
316+ const uint8_t * group_end )
317+ {
318+ int64_t v = webm -> pending_discard ;
319+ ebml_reader s ;
320+ webm -> pending_discard = 0 ;
321+ s .p = p ;
322+ s .end = group_end ;
323+ while (s .p < s .end )
324+ {
325+ int ok ;
326+ uint32_t id = ebml_read_id (& s );
327+ uint64_t sz = ebml_read_vint (& s , 1 , & ok );
328+ if (!id || !ok || s .p + sz > s .end )
329+ break ;
330+ if (id == ID_DISCARDPADDING && sz >= 1 && sz <= 8 )
331+ v = ebml_sint (s .p , (size_t )sz );
332+ s .p += sz ;
333+ }
334+ return v ;
335+ }
336+
301337int rwebm_read_packet (rwebm_t * webm , rwebm_packet * pkt )
302338{
303339 ebml_reader r ;
@@ -313,6 +349,8 @@ int rwebm_read_packet(rwebm_t *webm, rwebm_packet *pkt)
313349 pkt -> track = webm -> lace_track ;
314350 pkt -> timestamp = webm -> lace_ts ;
315351 pkt -> keyframe = webm -> lace_keyframe ;
352+ pkt -> discard_padding = (webm -> lace_index == webm -> lace_count )
353+ ? webm -> lace_discard : 0 ;
316354 return 1 ;
317355 }
318356
@@ -331,11 +369,23 @@ int rwebm_read_packet(rwebm_t *webm, rwebm_packet *pkt)
331369 if (id == ID_CLUSTER || id == ID_BLOCKGROUP )
332370 {
333371 /* Descend: Cluster holds Timestamp + blocks; BlockGroup wraps a
334- * single Block (plus duration/refs we ignore). Scan children. */
372+ * single Block (plus DiscardPadding/duration/refs). Scan
373+ * children. */
374+ if (id == ID_BLOCKGROUP )
375+ webm -> pending_discard = 0 ;
335376 r .p = body ;
336377 r .end = body + sz ;
337378 continue ;
338379 }
380+ if (id == ID_DISCARDPADDING )
381+ {
382+ /* Signed big-endian integer, nanoseconds; may precede the
383+ * Block within its BlockGroup. */
384+ if (sz >= 1 && sz <= 8 )
385+ webm -> pending_discard = ebml_sint (body , (size_t )sz );
386+ r .p = body + sz ;
387+ continue ;
388+ }
339389 if (id == ID_TIMESTAMP )
340390 {
341391 webm -> cluster_ts = (int64_t )be_uint (body , (size_t )sz );
@@ -379,6 +429,8 @@ int rwebm_read_packet(rwebm_t *webm, rwebm_packet *pkt)
379429 * webm -> timestamp_scale ;
380430 pkt -> keyframe = (id == ID_SIMPLEBLOCK )
381431 ? ((flags & 0x80 ) != 0 ) : 1 ;
432+ pkt -> discard_padding = (id == ID_BLOCK )
433+ ? webm_group_discard (webm , body + sz , r .end ) : 0 ;
382434 webm -> cur = body + sz ;
383435 return 1 ;
384436 }
@@ -451,6 +503,8 @@ int rwebm_read_packet(rwebm_t *webm, rwebm_packet *pkt)
451503 webm -> lace_track = tidx ;
452504 webm -> lace_ts = (webm -> cluster_ts + rel_ts )
453505 * webm -> timestamp_scale ;
506+ webm -> lace_discard = (id == ID_BLOCK )
507+ ? webm_group_discard (webm , body + sz , r .end ) : 0 ;
454508 webm -> lace_keyframe = (id == ID_SIMPLEBLOCK )
455509 ? ((flags & 0x80 ) != 0 ) : 1 ;
456510 for (j = 0 ; j < nframes ; j ++ )
@@ -468,6 +522,9 @@ int rwebm_read_packet(rwebm_t *webm, rwebm_packet *pkt)
468522 pkt -> track = webm -> lace_track ;
469523 pkt -> timestamp = webm -> lace_ts ;
470524 pkt -> keyframe = webm -> lace_keyframe ;
525+ pkt -> discard_padding =
526+ (webm -> lace_index == webm -> lace_count )
527+ ? webm -> lace_discard : 0 ;
471528 return 1 ;
472529 }
473530 }
0 commit comments