From b2be7a3862d5f5cadb355a570cab185f01a0eea1 Mon Sep 17 00:00:00 2001 From: Jan Gerber Date: Tue, 19 Nov 2013 03:45:00 +1300 Subject: [PATCH] Bug 938315 - Update nestegg to support Opus elements. r=kinetik Merge upstream changes to the WebM parser needed to properly support Opus. --- media/libnestegg/README_MOZILLA | 2 +- media/libnestegg/include/nestegg.h | 10 +++ media/libnestegg/src/nestegg.c | 107 +++++++++++++++++++++++------ 3 files changed, 98 insertions(+), 21 deletions(-) diff --git a/media/libnestegg/README_MOZILLA b/media/libnestegg/README_MOZILLA index ecfdfe06cc44..17dafbb5a27f 100644 --- a/media/libnestegg/README_MOZILLA +++ b/media/libnestegg/README_MOZILLA @@ -5,4 +5,4 @@ Makefile.in build files for the Mozilla build system. The nestegg git repository is: git://github.com/kinetiknz/nestegg.git -The git commit ID used was 26d262114af191b6654cbd5d24ec02e4b6bdb1cd. +The git commit ID used was 0851279ab11f5b2e9e8154ce7880b687b564c760. diff --git a/media/libnestegg/include/nestegg.h b/media/libnestegg/include/nestegg.h index 6f307aa398bf..ff13728f32a3 100644 --- a/media/libnestegg/include/nestegg.h +++ b/media/libnestegg/include/nestegg.h @@ -140,6 +140,8 @@ typedef struct { double rate; /**< Sampling rate in Hz. */ unsigned int channels; /**< Number of audio channels. */ unsigned int depth; /**< Bits per sample. */ + uint64_t codec_delay; /**< Nanoseconds that must be discarded from the start. */ + uint64_t seek_preroll;/**< Nanoseconds that must be discarded after a seek. */ } nestegg_audio_params; /** Logging callback function pointer. */ @@ -321,6 +323,14 @@ int nestegg_packet_count(nestegg_packet * packet, unsigned int * count); int nestegg_packet_data(nestegg_packet * packet, unsigned int item, unsigned char ** data, size_t * length); +/** Returns discard_padding for given packet + @param packet Packet initialized by #nestegg_read_packet. + @param discard_padding pointer to store discard padding in. + @retval 0 Success. + @retval -1 Error. */ +int nestegg_packet_discard_padding(nestegg_packet * packet, + int64_t * discard_padding); + /** Query the presence of cues. @param context Stream context initialized by #nestegg_init. @retval 0 The media has no cues. diff --git a/media/libnestegg/src/nestegg.c b/media/libnestegg/src/nestegg.c index b3bc9cb6dd0c..cd609c9e7b62 100644 --- a/media/libnestegg/src/nestegg.c +++ b/media/libnestegg/src/nestegg.c @@ -49,6 +49,7 @@ #define ID_BLOCK 0xa1 #define ID_BLOCK_DURATION 0x9b #define ID_REFERENCE_BLOCK 0xfb +#define ID_DISCARD_PADDING 0x75a2 /* Tracks Elements */ #define ID_TRACKS 0x1654ae6b @@ -63,6 +64,8 @@ #define ID_LANGUAGE 0x22b59c #define ID_CODEC_ID 0x86 #define ID_CODEC_PRIVATE 0x63a2 +#define ID_CODEC_DELAY 0x56aa +#define ID_SEEK_PREROLL 0x56bb /* Video Elements */ #define ID_VIDEO 0xe0 @@ -194,6 +197,7 @@ struct info { struct block_group { struct ebml_type duration; struct ebml_type reference_block; + struct ebml_type discard_padding; }; struct cluster { @@ -230,6 +234,8 @@ struct track_entry { struct ebml_type language; struct ebml_type codec_id; struct ebml_type codec_private; + struct ebml_type codec_delay; + struct ebml_type seek_preroll; struct video video; struct audio audio; }; @@ -305,6 +311,7 @@ struct nestegg_packet { uint64_t track; uint64_t timecode; struct frame * frame; + int64_t discard_padding; }; /* Element Descriptor */ @@ -368,6 +375,7 @@ static struct ebml_element_desc ne_block_group_elements[] = { E_SUSPEND(ID_BLOCK, TYPE_BINARY), E_FIELD(ID_BLOCK_DURATION, TYPE_UINT, struct block_group, duration), E_FIELD(ID_REFERENCE_BLOCK, TYPE_INT, struct block_group, reference_block), + E_FIELD(ID_DISCARD_PADDING, TYPE_INT, struct block_group, discard_padding), E_LAST }; @@ -409,6 +417,8 @@ static struct ebml_element_desc ne_track_entry_elements[] = { E_FIELD(ID_LANGUAGE, TYPE_STRING, struct track_entry, language), E_FIELD(ID_CODEC_ID, TYPE_STRING, struct track_entry, codec_id), E_FIELD(ID_CODEC_PRIVATE, TYPE_BINARY, struct track_entry, codec_private), + E_FIELD(ID_CODEC_DELAY, TYPE_UINT, struct track_entry, codec_delay), + E_FIELD(ID_SEEK_PREROLL, TYPE_UINT, struct track_entry, seek_preroll), E_SINGLE_MASTER(ID_VIDEO, TYPE_MASTER, struct track_entry, video), E_SINGLE_MASTER(ID_AUDIO, TYPE_MASTER, struct track_entry, audio), E_LAST @@ -1365,6 +1375,35 @@ ne_read_block(nestegg * ctx, uint64_t block_id, uint64_t block_size, nestegg_pac return 1; } +static int +ne_read_discard_padding(nestegg * ctx, nestegg_packet * pkt) +{ + int r; + uint64_t id, size; + struct ebml_element_desc * element; + struct ebml_type * storage; + + r = ne_peek_element(ctx, &id, &size); + if (r != 1) + return r; + + if (id != ID_DISCARD_PADDING) + return 1; + + element = ne_find_element(id, ctx->ancestor->node); + if (!element) + return 1; + + r = ne_read_simple(ctx, element, size); + if (r != 1) + return r; + storage = (struct ebml_type *) (ctx->ancestor->data + element->offset); + pkt->discard_padding = storage->v.i; + + return 1; +} + + static uint64_t ne_buf_read_id(unsigned char const * p, size_t length) { @@ -1994,34 +2033,40 @@ nestegg_track_codec_data(nestegg * ctx, unsigned int track, unsigned int item, if (!entry) return -1; - if (nestegg_track_codec_id(ctx, track) != NESTEGG_CODEC_VORBIS) + if (nestegg_track_codec_id(ctx, track) != NESTEGG_CODEC_VORBIS + && nestegg_track_codec_id(ctx, track) != NESTEGG_CODEC_OPUS) return -1; if (ne_get_binary(entry->codec_private, &codec_private) != 0) return -1; - p = codec_private.data; - count = *p++ + 1; + if (nestegg_track_codec_id(ctx, track) == NESTEGG_CODEC_VORBIS) { + p = codec_private.data; + count = *p++ + 1; - if (count > 3) - return -1; + if (count > 3) + return -1; - i = 0; - total = 0; - while (--count) { - sizes[i] = ne_xiph_lace_value(&p); - total += sizes[i]; - i += 1; + i = 0; + total = 0; + while (--count) { + sizes[i] = ne_xiph_lace_value(&p); + total += sizes[i]; + i += 1; + } + sizes[i] = codec_private.length - total - (p - codec_private.data); + + for (i = 0; i < item; ++i) { + if (sizes[i] > LIMIT_FRAME) + return -1; + p += sizes[i]; + } + *data = p; + *length = sizes[item]; + } else { + *data = codec_private.data; + *length = codec_private.length; } - sizes[i] = codec_private.length - total - (p - codec_private.data); - - for (i = 0; i < item; ++i) { - if (sizes[i] > LIMIT_FRAME) - return -1; - p += sizes[i]; - } - *data = p; - *length = sizes[item]; return 0; } @@ -2110,6 +2155,14 @@ nestegg_track_audio_params(nestegg * ctx, unsigned int track, ne_get_uint(entry->audio.bit_depth, &value); params->depth = value; + value = 0; + ne_get_uint(entry->codec_delay, &value); + params->codec_delay = value; + + value = 0; + ne_get_uint(entry->seek_preroll, &value); + params->seek_preroll = value; + return 0; } @@ -2135,6 +2188,13 @@ nestegg_read_packet(nestegg * ctx, nestegg_packet ** pkt) /* The only DESC_FLAG_SUSPEND fields are Blocks and SimpleBlocks, which we handle directly. */ r = ne_read_block(ctx, id, size, pkt); + if (r != 1) + return r; + + r = ne_read_discard_padding(ctx, *pkt); + if (r != 1) + return r; + return r; } @@ -2175,6 +2235,13 @@ nestegg_packet_tstamp(nestegg_packet * pkt, uint64_t * tstamp) return 0; } +int +nestegg_packet_discard_padding(nestegg_packet * pkt, int64_t * discard_padding) +{ + *discard_padding = pkt->discard_padding; + return 0; +} + int nestegg_packet_count(nestegg_packet * pkt, unsigned int * count) {